个人二次封装的tree组件,有不对的地方,可以在评论区指出我的问题!
此组件支持单选,限制勾选数量及不限制数量多选,勾选达到限制数量的情况下,其他复选框自动变成禁用状态,在取消选择第 限制数量 框时复选框禁用状态恢复可用,且文字点击和复选框的点击不会冲突
效果图:
组件源码如下
<template>
<div style="display: flex;">
<el-checkbox v-model="isAll" @change="change" v-if="allFlag&&treeData.length!=0" style="margin-right: 14px;">全选</el-checkbox>
<el-tree
ref="tree"
:data="menuData"
v-on="$listeners"
v-bind="$attrs"
@node-click="nodeClick"
@check="checkClick"
@check-change="handleCheckChange"
:default-expanded-keys="expandedKey"
:default-checked-keys="checkedKey"
/>
</div>
</template>
<script>
export default {
name:'TreeSelect',
props:{
expandedKey:{
type:Array,
default:()=>[]
},
checkedKey:{
type:Array,
default:()=>[]
},
maxSelect:{
type:Number,
default:()=>0
},
allFlag:{
type:Boolean,
default:()=>false,
},
treeData:{
type:Array,
default:()=>[]
},
total:{
type:Number,
default:()=>0
},
},
data(){
return{
isNodeClick:false,
isAll:false,
menuData:[],
}
},
methods:{
backFill(){
this.menuData = this.$deepCopy(this.treeData)
if(this.total==this.$refs.tree.getCheckedKeys().length) this.isAll = true
},
handleCheckChange(a,b,c){
if(!b&&this.allFlag) this.isAll=false
if(this.total==this.$refs.tree.getCheckedKeys().length) this.isAll = true
this.$emit('input',this.$refs.tree.getCheckedKeys())//回数组
},
change(val){
if (val) this.$refs.tree.setCheckedNodes(this.menuData)
else this.$refs.tree.setCheckedNodes([])
},
checkClick(data, treeInfo){
if(this.isNodeClick){
this.isNodeClick=false
return
}
if(this.maxSelect==0){//不限制可选数量
this.$emit('input',this.$refs.tree.getCheckedKeys())//回数组
}else{//限制可选数量
if(this.maxSelect==1){
if (treeInfo.checkedKeys.length) {
//单选实现
this.$refs.tree.setCheckedKeys([data.id]);
this.$emit('input',this.$refs.tree.getNode(data.id).data.id)//回id
} else {
//取消当前选中节点
this.$refs.tree.setCheckedKeys([]);
this.$emit('input','')
}
}
else this.check(data)
}
this.$emit("getNode",this.$refs.tree.getNode(data.id))
},
nodeClick(data, treeInfo){
if(treeInfo.childNodes.length!=0) return
if(this.$refs.tree.lazy) return//懒加载情况下不适用node点击勾选复选框情况
this.isNodeClick=true
if(this.maxSelect==0){//不限制可选数量
this.$emit('input',this.$refs.tree.getCheckedKeys())//回数组
}else{//限制可选数量
if(treeInfo.data.disabled) return
if(this.maxSelect==1){//单选
if (treeInfo.checked) {
this.$refs.tree.setCheckedKeys([data.id]);
this.$emit('input',this.$refs.tree.getNode(data.id).data.id)//回id
} else {
this.$refs.tree.setCheckedKeys([]);
this.$emit('input','')
}
}
else this.check(data)
}
},
check(data){
let treeNodesMap = this.$refs.tree.store?.nodesMap || {};
let status = this.maxSelect==this.$refs.tree.getCheckedKeys().length
if (status) {
// this.$message.error(`最多可选择${this.maxSelect}个`)
Object.keys(treeNodesMap).forEach(key => {
let item = treeNodesMap[key] || {};
if (!this.$refs.tree.getCheckedKeys().includes(parseInt(key))) {
let data = item.data || {};
data.disabled = status;
//设置其他的展开点击为不可选取
this.$refs.tree.setCurrentNode(data);
}
})
}
else{
this.options.forEach(item=>{
item.disabled=true
item.children.forEach(item1=>{
item1.disabled=false
})
})
}
this.$emit('input',this.$refs.tree.getCheckedKeys())//回id
}
},
}
</script>
<style lang="less" scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
/deep/.el-tree__empty-text{
position: relative !important;
}
</style>
父组件源码如下:
<TreeSelect
:options="depData"
node-key="id"
show-checkbox
highlight-current
check-on-click-node
check-strictly
:expandedKey="[addParams.depId]"
:checkedKey="[addParams.depId]"
:maxSelect="1"
@input="input"
/>
input(val){
this.addParams.depId = val
},