VUE使用element的el-tree封装1

174 阅读2分钟

element的el-tree组件,选中事件父子级的选中只有强关联和不关联两种可用,无法满足我们项目中部分tree半关联的需求。

封装的tree满足:

node节点checkType : 1 或者 undefine  未选中    2 选中   3 半选中
1. 选中A     直上 父级选中
            直下 子级选中
2. 取消A     直上 父级不变    若父级无选中的子级  半选的父级改为1 未选
            直下 子级不取消
3. 无半选中

属性:
props:
    propsConfig:        //  el-tree 配置   
        {
            label: 'menuName',   
            children: 'childrenList'
        }
    datasource: [],
    checkList: [],
    nodekey: '',
    vt: new date().valueOf();
    event:
        onChange:  // 选择事件    []

封装代码如下

<el-tree 
    :data="treeData"
    :node-key="nodekey"
    :expand-on-click-node="false"
    :props="propsConfig"
    >
    <span class="ui-halftree-custom-tree-node" slot-scope="{ node, data }">
        <div :key="data.id" class="check-box" @click.stop.prevent="toggleSelect(data, node)">
            <el-checkbox v-if="data.checkType == 2" checked ></el-checkbox>
            <el-checkbox v-else-if="data.checkType == 3" checked indeterminate ></el-checkbox>
            <el-checkbox v-else ></el-checkbox>
            <span class="check-mask"></span>
        </div>

        <span>{{ node.label }}</span>
    </span>
</el-tree>
props: {
    propsConfig: {
        type: Object,
        default: () => {}
    },
    nodekey: {
        type: String,
        default: 'id'
    },
    datasource: {
        type: Array,
        default: () => []
    },
    checkList: {
        type: Array,
        default: () => []
    },
    vt: {
        type: Number | String,
        default: 1
    },
},
data() {
    return {
        treeData: [],
    };
},
watch: {
    vt: {
        handler: function(newVal, oldVal) {
                                this.initData();
        },
        immediate: true,
    },
},
methods: {
            initData() {
                this.treeData = cloneDeep(this.datasource);
                this.initTreeData();
            },
            initTreeData() {
                if(this.checkList.length > 0) {
                    let childName = this.propsConfig.children || 'children';
                    this.initCheckData(this.treeData, childName);
                    this.dealCheckData(this.treeData, childName);

                    this.dealCheckArr();
                }
            },
            initCheckData(arr, childName) {
                arr.forEach(i => {
                    if(i && i[this.nodekey] && includes(this.checkList, i[this.nodekey])) {
                        i.checkType = 2;
                    } else {
                        i.checkType = 1;
                    }
                    if(i && i[childName] && i[childName].length > 0) {
                        this.initCheckData(i[childName], childName)
                    }
                });
            },
            dealCheckData(arr, childName) {
                let res = false;
                let childRes = false;
                arr.forEach(i => {
                    if(i && i.checkType == 2) {
                        res = true;
                        if(i && i[childName] && i[childName].length > 0) {
                            this.dealCheckData(i[childName], childName);
                        }
                    } else if(i && i[childName] && i[childName].length > 0) {
                        childRes = this.dealCheckData(i[childName], childName);
                        if(childRes) {
                            res = true;
                            if(!i.checkType || i.checkType == 1) {
                                i.checkType = 3;
                            }
                        } else {
                            if(!i.checkType || i.checkType == 3) {
                                i.checkType = 1;
                            }
                        }
                    }
                });
                return res;
            },


            toggleSelect(data, node) {
                // let ctype = 1;
                // data.checkType = 3 - (data.checkType || 1);
                let childName = this.propsConfig.children || 'children';


                let isHasChildCheck = false;
                if(data && data[childName] && data[childName].length > 0) {
                    isHasChildCheck = this.judgeCheckData(data[childName], childName);
                }

                if(!data.checkType || data.checkType == 1 || data.checkType == 3) {
                    data.checkType = 2;
                } else {
                    data.checkType = isHasChildCheck ? 3 : 1;
                }

                if(data.checkType == 2) { // 选中
                    if(data[childName] && data[childName].length > 0) {
                        !isHasChildCheck && this.checkChildArr(data[childName], childName); // 子选中
                    }
                    this.dealCheckData(this.treeData, childName);
                } else { // 未选中
                    this.dealCheckData(this.treeData, childName);
                }
                this.dealCheckArr();

            },
            judgeCheckData(arr, childName) {
                let res = false;
                let childRes = false;
                arr.forEach(i => {
                    if(i && i.checkType == 2) {
                        res = true;
                    } else if(i && i[childName] && i[childName].length > 0) {
                        childRes = this.judgeCheckData(i[childName], childName);
                        if(childRes) {
                            res = true;
                        }
                    }
                });
                return res;
            },


            checkParentArr(list, itemId, childName){
                let res = false;
                let childRes = false;
                list.forEach(i => {
                   
                    if(i && i[this.nodekey]  && i[this.nodekey] == itemId) {
                        res = true;
                    } else {
                        if(i && i[childName] && i[childName].length > 0) {
                            childRes = this.checkParentArr(i[childName], itemId, childName);
                            if(childRes) {
                                res = true;
                                i.checkType = 2;
                            }
                        }
                    }
                });
                return res;
            },
            checkChildArr(list, childName){
                list.forEach(i => {
                    if(i && i[this.nodekey]) {
                        i.checkType = 2;
                    }
                    if(i && i[childName] && i[childName].length > 0) {
                        this.checkChildArr(i[childName], childName);
                    }
                });
            },
            cancleChildArr(list, childName){
                // let childName = this.propsConfig.children || 'children';
                list.forEach(i => {
                    if(i && i[this.nodekey]) {
                        i.checkType = 1;
                    }
                    if(i && i[childName] && i[childName].length > 0) {
                        this.cancleChildArr(i[childName], childName);
                    }
                });
            },
            getCheckKey(arr, childName) {
                let res = [];
                arr.forEach(i => {
                    if(i && i[this.nodekey]) {
                        if(i.checkType == 2) {
                            res.push(i);
                        }
                    }
                    if(i && i[childName] && i[childName].length > 0) {
                        res = res.concat(this.getCheckKey(i[childName], childName));
                    }
                });

                return res;
            },
            dealCheckArr() {
                let list = [];
                let arr = cloneDeep(this.treeData);
                let childName = this.propsConfig.children || 'children';
                list = this.getCheckKey(arr, childName);
                this.$emit('onChange', list);
            }
        }
.ui-halftree-custom-tree-node {
    .check-box {
        position: relative;
        display: inline-block;
        margin-right: 0.4rem;
    }
    .check-mask {
        position: absolute;
        display: inline-block;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        z-index: 5;
    }
}