React 下拉多選,全選/全不選功能組件


組件名:checkbox-select

組件截圖:

 

文件內容:

src/pages/checkbox-select/index.js

import CheckboxSelect from 'components/checkbox-select';

function Page() {
    // 演示數據
    const testList = [
        { label: '#演示項目 1', value: 1 },
        { label: '#演示項目 2', value: 2 },
        { label: '#演示項目 3', value: 3 },
        { label: '#演示項目 4', value: 4 },
        { label: '#演示項目 5', value: 5 },
        { label: '#演示項目 6', value: 6 },
        { label: '#演示項目 7', value: 7 },
        { label: '#演示項目 8', value: 8 },
    ];

    // 選擇返回數據
    const changeCallback = (data) => {
        console.log('callback data---->', data);
    };

    return (
        <>
            <CheckboxSelect optionsList={testList} changeCallback={changeCallback} />
        </>
    );
}

export default Page;
View Code

src/components/checkbox-select/index.js

/**
 * 包含多選框的下拉列表,含全選和全不選操作
 * */
import { useEffect, useState, useCallback, useRef } from 'react';
import PropTypes from 'prop-types';
import { Checkbox, Button } from 'antd';
import 'less/components/checkbox-select/index.less';

function CheckboxSelect(props) {
    const { optionsList, changeCallback } = props;

    const cancelBtn = useRef();
    const [showText, setShowText] = useState('全部');
    const [isActive, setIsActive] = useState(false);
    const [checkAll, setCheckAll] = useState(true);
    const [indeterminate, setIndeterminate] = useState(false);
    const [checkboxValList, setCheckboxValList] = useState([]);
    const [checkboxOldValList, setCheckboxOldValList] = useState([]);

    // 多選框列表被觸發的時候
    const checkboxChange = (list) => {
        setCheckboxValList(list);
        setIndeterminate(!!list.length && list.length < optionsList.length);
    };
    // 確定操作
    const confirm = () => {
        setCheckboxOldValList(checkboxValList);
        setIsActive(false);

        // 返回最終數據
        changeCallback(checkboxValList);

        // 把選擇的文本顯示在框框內
        if (checkboxValList.length === optionsList.length) {
            setShowText('全部');
            return;
        }
        const textArr = [];
        optionsList.forEach((item1) => {
            checkboxValList.forEach((item2) => {
                if (item1.value === item2) {
                    textArr.push(item1.label);
                }
            });
        });
        setShowText(textArr.join(','));
    };
    // 取消操作
    const cancel = () => {
        setCheckboxValList(checkboxOldValList);
        setIsActive(false);
    };
    // 點擊操作
    const toggleClick = (ev) => {
        // 阻止事件冒泡
        ev.nativeEvent.stopImmediatePropagation();
        const status = !isActive;
        setIsActive(status);
    };

    // 全選/全不選 操作
    const onCheckAllChange = () => {
        const status = !checkAll;
        setCheckAll(status);

        // 判斷是全選還是全不選
        const listArr = [];
        if (status) {
            optionsList.forEach((item) => {
                listArr.push(item.value);
            });
        }
        setCheckboxValList(listArr);
        setIndeterminate(false);
    };

    // 觸發內容區域
    const documentEvent = () => {
        cancelBtn.current.click();
    };

    // 監聽全選/全不選狀態
    useEffect(() => {
        setCheckAll(optionsList.length === checkboxValList.length);
        setIndeterminate(!!checkboxValList.length && checkboxValList.length < optionsList.length);
    }, [checkboxValList]);

    // 組件卸載
    const unComponent = () => {
        // console.log('組件卸載');
        document.removeEventListener('click', documentEvent);
    };

    // 初始操作
    const init = useCallback(() => {
        // 設置checkbox默認全選
        const listArr = [];
        optionsList.forEach((item) => {
            listArr.push(item.value);
        });
        setCheckboxValList(listArr);
        setCheckboxOldValList(listArr);
        // 空白文檔處被點擊
        document.addEventListener('click', documentEvent);
    }, []);

    useEffect(() => {
        init();
        return unComponent;
    }, []);

    return (
        <>
            <div className={`checkbox-select ${isActive ? 'checkbox-select-active' : ''}`}>
                <div className="cs__input-wrap" onClick={toggleClick}>
                    <div className="cs__input-text">{showText}</div>
                    <span className="cs__input-icon"></span>
                </div>
                <div
                    className="cs__tool"
                    onClick={(ev) => {
                        ev.nativeEvent.stopImmediatePropagation();
                    }}
                >
                    <Checkbox.Group onChange={checkboxChange} value={checkboxValList}>
                        <ul className="cs__checkbox-list">
                            {optionsList.length ? (
                                optionsList.map((item) => {
                                    return (
                                        <li key={item.value}>
                                            <Checkbox value={item.value}>{item.label}</Checkbox>
                                        </li>
                                    );
                                })
                            ) : (
                                <li className="empty">暫無數據</li>
                            )}
                        </ul>
                    </Checkbox.Group>

                    <div className="cs__button" style={{ display: optionsList.length ? '' : 'none' }}>
                        <Checkbox indeterminate={indeterminate} onChange={onCheckAllChange} checked={checkAll}>
                            全選/全不選
                        </Checkbox>
                        <Button type="primary" size="small" onClick={confirm}>
                            確定
                        </Button>
                        <Button size="small" onClick={cancel} ref={cancelBtn}>
                            取消
                        </Button>
                    </div>
                </div>
            </div>
        </>
    );
}

CheckboxSelect.propTypes = {
    //下拉列表數據
    optionsList: PropTypes.array,
    // 確定按鈕觸發返回函數:return array
    changeCallback: PropTypes.func,
};

CheckboxSelect.defaultProps = {
    optionsList: [],
};

export default CheckboxSelect;
View Code

src/less/components/checkbox-select/index.less

* {
    padding: 0;
    margin: 0;
    list-style: none;
}

// --------------------------------------- 組件樣式開始 ---------------------------------
@keyframes fadeIn {
    0% {
        opacity: 0;
    }
    100% {
        opacity: 1;
    }
}

.checkbox-select {
    margin: 0px auto;
    top: 100px;

    max-width: 260px;
    position: relative;
    .cs__input-wrap {
        position: relative;
        cursor: pointer;
        .cs__input-text {
            width: 100%;
            padding: 0 30px 0 10px;
            height: 34px;
            line-height: 34px;
            border: 1px solid #ddd;
            user-select: none;
            white-space: nowrap;
            text-overflow: ellipsis;
            overflow: hidden;
        }
        .cs__input-icon {
            position: absolute;
            display: block;
            right: 1px;
            top: 1px;
            height: 32px;
            width: 30px;
            &::after {
                content: ' ';
                display: block;
                width: 0;
                height: 0;
                border-left: 5px solid transparent;
                border-right: 5px solid transparent;
                border-top: 8px solid #555;
                position: absolute;
                left: 50%;
                top: 50%;
                transform: translate(-50%, -50%);
            }
        }
    }
    .cs__tool {
        display: none;
        position: absolute;
        width: 100%;
        left: 0;
        top: 34px;
        background-color: #fff;
        border: 1px solid #f1f1ff;
        animation: fadeIn 0.5s 0s;
        .cs__checkbox-list {
            margin-bottom: 0;
            max-height: 200px;
            overflow: hidden auto;
            label {
                padding: 5px 10px;
                &:hover {
                    background-color: #f1f1f1;
                }
            }
            .ant-checkbox-wrapper {
                width: 100%;
            }
            .empty {
                text-align: center;
                min-height: 100px;
                line-height: 100px;
                font-size: 12px;
                color: #999;
            }
        }

        .ant-checkbox-group {
            padding-top: 5px;
            width: 100%;
        }
        .cs__button {
            width: 100%;
            border-top: 1px solid #f1f1f1;
            padding: 5px 10px;
            display: inline-block;
            label {
                font-size: 12px;
                user-select: none;
                color: #555;
            }
            button {
                margin: 0 5px;
                float: right;
            }
            .ant-btn-primary {
                margin-right: 0;
            }
        }
    }
}
.checkbox-select-active {
    .cs__tool {
        display: block;
    }
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM