最近使用 vue+element UI 框架开发前端项目,用到比较多的是 Cascader 级联选择器。使用过程中有一些心得借此机会跟大家分享一下。 Cascader 级联选择器就是当一个数据集合有清晰的层级结构时,可通过级联选择器逐级查看并选择。在 Element 官网上可以查到它的基础用法,代码如下:
<div class="block">
<span class="demonstration">hover 触发子菜单</span>
<el-cascader
v-model="value"
:options="options"
:props="{ expandTrigger: 'hover' }"
@change="handleChange"></el-cascader>
</div>
它默认的触发方式是 click,如果选择 hover 方式触发,可以对 props 参数设置,将 Trigger 方式改为 hover。 在我的项目中,我想做一个按钮,当鼠标移至按钮时就出现级联选项菜单,当选中选项后就跳转到相关的内容。所以这边结合了 Popover 弹出框和 button 按钮一起使用,参考代码如下:
<div id="button-cascader">
<el-popover
ref="popover"
class="popover"
placement="bottom-start"
:trigger="trigger"
@show="btnAction"
>
<el-cascader-panel
ref="panel"
v-model="selected"
:props="{ expandTrigger: 'hover',value: 'id', label: 'name' }"
:options="options"
:border="false"
@change="selectedAction"
/>
<button ref="button" slot="reference" class="button" :type="buttonType">
{{ buttonText }}
</button>
</el-popover>
</div>
页面效果图如下:
但是在测试的时候发现一个问题,就是已选中的选项会被绑定,下次就不能再选,但是我不想这样,我希望每次弹出的菜单都是新的。所以就在每次触发成功时,用 @show 事件去调用 btnAction 方法将绑定值 selected 清空或者使用 this.$refs.panel.clearCheckedNodes() 来清空选中数据。 我这边使用的是将 selected 数据清空,这样的下拉菜单只显示父级,子级不会显示出来。 另外我想实现选中选项后除了可以跳转到相关内容,还希望展示路径,那我这里就用了 Breadcrumb 面包屑,代码如下:
<el-breadcrumb
v-if="showTable && !isShowSearch"
separator-class="el-icon-arrow-right"
style="margin: 20px"
>
<el-breadcrumb-item>
<span style="font-weight:bold">
{{pathLabel[0]}}
</span>
</el-breadcrumb-item>
<el-breadcrumb-item>
{{ pathLabel[1] }}
</el-breadcrumb-item>
</el-breadcrumb>
这里需要获得 Cascader 级联选择器选中的选项路径 label 值。这里我们可以在选项改变时通过 @change 事件来触发 seclectedAction 方法,使用 this.$refs['panel'].getCheckedNodes()[0].pathLabels 来取得节点 label。这样就可以获得相应的路径了。 页面效果图如下:
项目中还遇到一个问题,我希望 Cascader 级联选择器默认第一个选项。options 的数据格式是树形结构,如下所示:
[
{
"id": 1,
"pid": 0,
"name": "电阻",
"created_at": "2022/02/10",
"children": [
{
"id": 3,
"pid": 1,
"name": "贴片电阻",
"created_at": "2022/02/10"
},
{
"id": 4,
"pid": 1,
"name": "插件电阻",
"created_at": "2022/02/10"
}
]
},
{
"id": 5,
"pid": 0,
"name": "电容",
"created_at": "2022/02/14",
"children": [
{
"id": 7,
"pid": 5,
"name": "钽电容",
"created_at": "2022/02/14"
},
{
"id": 9,
"pid": 5,
"name": "贴片型铝电解电容",
"created_at": "2022/02/14"
},
{
"id": 10,
"pid": 5,
"name": "薄膜电容",
"created_at": "2022/02/15"
},
{
"id": 14,
"pid": 5,
"name": "固态电容",
"created_at": "2022/02/17"
}
]
},
{
"id": 17,
"pid": 0,
"name": "连接器",
"created_at": "2022/02/22",
"children": [
{
"id": 18,
"pid": 17,
"name": "排针",
"created_at": "2022/02/22"
}
]
}
]
我开始是采用简单的取数组值 options[0].children[0].id,如果这个菜单树是不变的,这样好像不会有问题,但是菜单树是变化的,如果 children 不存在就会报错。所以这里采用一个递归函数来无限向下获取子节点。参考代码如下:
searchChildren(arr) {
var newArr = [];
for (var item = 0; item < arr.length; item++) {
newArr.push(arr[item]['id']);
if (arr[item].children) {
newArr[item] = this.searchChildren(arr[item].children);
}
}
return newArr;
}
这样就可以获得每个菜单树的子节点了,通过函数调用来获取想要的子节点。 页面效果如下:
关于 Cascader 级联选择器 的分享就写到这里,如果后续还有会再补充进来。希望可以帮助到有类似需求的人。