对element的el-tree组件的封装,需满足:
checkType : 1 或者 undefine 未选中 2 选中 3 半选中
1. 选中A 直上 父级选中
直下 子级选中
2. 取消A 直上 父级不变
直下 子级取消
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 ></el-checkbox>
<span class="check-mask"></span>
</div>
<span>{{ node.label }}</span>
</span>
</el-tree>
import { cloneDeep, includes } from 'lodash'
export default {
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.initCheckData();
},
initCheckData() {
if(this.checkList.length > 0) {
let childName = this.propsConfig.children || 'children';
this.dealCheckData(this.treeData, childName);
}
},
dealCheckData(arr, childName) {
arr.forEach(i => {
if(i && i[this.nodekey] && includes(this.checkList, i[this.nodekey])) {
i.checkType = 2;
}
if(i && i[childName] && i[childName].length > 0) {
this.dealCheckData(i[childName], childName)
}
});
},
toggleSelect(data, node) {
data.checkType = 3 - (data.checkType || 1);
let childName = this.propsConfig.children || 'children';
if(data.checkType == 2) { // 选中
if(data[childName] && data[childName].length > 0) {
this.checkChildArr(data[childName], childName);
}
this.checkParentArr(this.treeData, data[this.nodekey], childName);
} else { // 未选中
this.cancleChildArr(data[childName], childName);
}
this.dealCheckArr();
},
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){
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[this.nodekey]);
}
}
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;
}
}