前言
最近碰到一个需求,要求选择器的下拉选项是树形结构,这个需求之前我也碰到过,当时时间紧匆匆做出来了,效果不太好,再次做该需求就好好找了一个实例进行了修改,下面我们来看一下具体的实现过程。
思路
这种组件之间的结合很考验我们对组件的熟悉度,el-select的el-option变成el-tree就是一个简单的书香选择器,查看el-select,下拉类别的插槽就是默认插槽。

我们用el-select去包裹el-tree就能得到一个树形选择器。
得到的效果图如下:
后续我们调整下组件的样式就能得到简便的树形选择器,该选择器主要是样式不太好看,用起来不是特别连贯。我们再翻一下element ui会发现Popover弹出框,弹出框由两部分组成:
- 触发元素,用来触发弹出框的HTML元素,可以用reference插槽自定义元素。
- 弹出框,用来展示内容,该内容可以进行嵌套多种类型的信息,比如展示表格、表单,树形结构也能够支持。
js
<el-popover>
展示内容
<el-button slot="reference">触发元素</el-button>
</el-popover>
将el-select变成触发元素,el-tree用作弹出框展示内容,我们就能通过el-popover得到一个树形选择器,而且使用el-popover一个组件整体,样式效果比最开始的样式好多了。
el-popover实现
经过上述的研究我们可以先把静态页面写出来,注意el-select要用refernce插槽才能显示出来。

接下来就是来完善业务逻辑,el-select与el-tree之间联动业务我们要梳理清楚,我们从这两个组件的角度去分析。
el-tree
在我们二次封装时,组件原有属性都可以当作props参数,对于el-tree最重要的是以下两个原有属性:
- show-checkbox:是否可选择,它对应着树形选择器是否能多选,当设置为true就意味着该选择器可以多选,业务的处理逻辑也与之相关。
- node-key:表示value字段,由具体的数据决定。
剩下的属性如check-strictly、check-on-click-node如果需要我们就设置为props参数。在树形选择器中el-tree做的就是赋值,比如在多选模式,我们选中三个节点,那么el-select绑定的数据就有三个。当我们选择节点时需要做以下事情: - 将选中的节点赋值给el-select绑定的值selected。单选时,利用el-tree中的getCurrentKey方法;多选时,利用getCheckedKeys方法获取选中节点,然后赋值给selected。
- 将选中节点的label、value对象,赋值给el-option绑定的值options。单选采用getCurrentNode;多选采用getCheckedKeys。
上述事件触发的事件一个是node-click,一个是check-change。注意check-change用于处理多选逻辑,如果我们将check-on-click-node设置为true,name在处理node-click时也要考虑多选逻辑。
el-select
el-select自带属性有很多,关键属性只有一个:
- multiple:是否多选,与el-tree的show-check相关联,multiple为true时,show-check必定为true。
剩下的属性如filterabel、clearble自行设置。el-slect要做的是设置节点状态,比如输入框有三个选项,去除一个选项,再点开el-tree去除的选项对应的节点不再选择。具体的设置主要分为以下情况: - 多选时清除一个,对应的事件为remove-tag,利用setChecked将el-tree对应的节点设置为false。
js
;(this.$refs.tree as Tree).setChecked(val, false, false)
注意,如果我们的check-strictly为false,那么我们就需要循环找到当前节点的后代节点也设置为false。
- 全部清除,对应事件为clear。这时候我们需要将所有选择的节点清空,单选时用clearSelectedNode;多选时选用clearSelectedNodes。
到此我们就将el-select与el-tree关联梳理清楚了,最后我们通过el-popover绑定值showFlag将两者结合起来,当el-select点击时showFlag为true弹出el-tree;当el-popover触发隐藏事件时,showFlag为false,el-tree消失。

总结
以上就是树形选择器实现的思路过程,通过el-popover当作桥梁,利用el-select与el-tree自带的方法去实现,特别是el-tree相关方法。