在项目中我们可能会遇到需要下拉然后出现一颗树的需求,类似下图
那么我们就着手来实现这个功能吧!
首先我们先来实现最基本的下拉树
<template>
<el-select
class="ld-select"
clearable
:value="valueTitle"
filterable
:filter-method="remoteMethod"
@clear="clearHandle"
placeholder="请输入"
popper-class="ld-select_tree-drop"
@focus="changeDefaultCheck"
>
<el-option :value="valueTitle">
<el-tree
show-checkbox
accordion
node-key="id"
:check-strictly="true"
ref="selectTree"
:data="options"
:props="defaultProps"
:node-key="defaultProps.value"
@check="checkNode"
:default-checked-keys="defaultCheckNodes"
:filter-node-method="filterNode">
</el-tree>
</el-option>
<div class="ld-select_tree" disabled>
<el-button type="primary" @click="allotMenuConfirm" size="mini">确 定</el-button>
</div>
</el-select>
</template>
el-select的:valu="valueTitle",valueTitle我只是定义了一下,我这边并不需要展示他勾选了什么,因为树选用了showBox及一个确认按钮来确认最终选择。ps:如果不写value会报错
接下来是各个方法
remoteMethod
remoteMethod(val){
this.valueTitle = val
this.$refs.selectTree.filter(val) // 过滤搜索树中节点
}
clearHandle
clearHandle(){
this.valueTitle = ''
this.remoteMethod(this.valueTitle)
}
因为组件会涉及到反显的问题,所以使用:check-strictly="true"来取消掉了父子级间的关联,然后写了一些方法来实现点击勾选的效果
changeDefaultCheck 此方法写在select的focus事件触发时,主要是用来解决,回显时候,父被勾选子未全被勾选时,父依旧为全选状态的问题
changeDefaultCheck(){
// 改变默认选中的时候 子级未全选父级全选状态的问题(改为半选)
const defaultNodes = this.$refs.selectTree.getCheckedNodes()
defaultNodes.map((item)=>{
if(item.childList && item.childList.length > 0){
const currentNodes = this.$refs.selectTree.getNode(item)
this.changeParentStatus(currentNodes)
}
})
}
checkNode树的checkNode方法
checkNode(node, treeStatus){
const selected = treeStatus.checkedKeys.indexOf(node.id) // -1未选中
// 选中
if(selected === -1) {
this.changeParentAndChild(node) // 取消节点时的方法
} else {
// 勾子改变父
this.selectedParent(node)
// 勾父全选子
this.uniteChildSame(node, true)
}
}
changeParentAndChild取消节点的方法
changeParentAndChild(currentObj){
const currentNode = this.$refs.selectTree.getNode(currentObj)
if(currentNode.childNodes.length > 0){
// 被取消的如果有子 则走uniteChildSame方法去取消所有的子的选中状态
this.uniteChildSame(currentObj, false)
}