之前写后台管理系统时,遇到一个下面的需求,下面是最终完成的效果图。
实现的功能有:
1. 下拉 选择不同的类型——就是一个普通的select组件,下面并不做介绍
2. 通过关键字可以进行tree
树形结构的筛选,然后将筛选后的内容自动展开
3. tree组件中,每一条数据,鼠标移入后展示 增/删/改 图标,点击有对应的功能
下面直接上代码
一:tree
组件的使用
<a-tree
:treeData="treeData"
ref="treeNode"
v-if="treeData"
:showIcon="false"
class="tree-list"
:defaultExpandAll="true"
:expandedKeys.sync="defaultExpandedKeys"
tree-default-expand-all
:replaceFields="replaceFields"
>
</a-tree>
1. treeData :tree组件的数据源
2. ref:相当于id,可以通过此参数获取到dom结构
3. v-if:只有当有数据源的时候才显示组件
4. showIcon:设置成false,就不会展示默认的tree组件图标了,此时可以通过自定义图标的形式来展示自定义的效果了
5. class="tree-list":因为我进行了自定义的样式处理,此时添加一个类名用于与其他tree组件区分
6. defaultExpandAll:设置成true,默认展开所有节点,也可以通过下面的expandedKeys来指定展开的节点
7. expandedKeys:异步指定要展开的节点,用于筛选后所有符合条件的数据的展开
8. replaceFields:当数据源给定的数据结构与期望的结构不符时,可以通过此参数进行设置。
我这边的配置如下:
replaceFields: {
children: 'children',
title: 'title',
key: 'key',
value: 'subTitle',
},
二:使用插槽实现自定义组件结构
<a-icon slot="switcherIcon" type="caret-down" />
<template slot="custom" slot-scope="item">
<div @mouseenter="mouseenter(item)" style="position: relative">
<span
style="
height: 30px;
width: 70%;
display: flex;
align-items: center;
"
>
<a-icon
type="home"
theme="filled"
style="
height: 30px;
line-height: 30px;
padding-right: 5px;
"
v-if="item.slots.Code"
/>
<a-icon
type="user"
style="
height: 30px;
line-height: 30px;
padding-right: 5px;
"
v-if="item.slots.UserId"
/>
<span
style="
height: 30px;
display: inline-block;
max-width: 80%;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 5px;
"
>{{ item.title }}</span
>
<span
style="
height: 30px;
display: inline-block;
max-width: 80%;
overflow: hidden;
color: #f90;
font-weight: bold;
height: 30px;
"
>
<span v-if="item.slots.IsSecondary"
>[兼]</span
>
<span v-if="item.slots.IsLeader"
>[责]</span
>
</span>
</span>
<a-space
@click.stop
v-if="currentId == item.key"
style="position: absolute; right: 25px; top: 0"
>
<a-icon
type="plus-square"
style="color: green"
@click.stop="handleAdd(item)"
v-if="item.key.indexOf('U') == -1"
/>
<a-icon type="edit" @click.stop="handleEdit(item)" />
<a-icon
type="delete"
@click.stop="handleDel(item)"
style="color: red"
v-if="item.key.indexOf('U') == -1"
/>
</a-space>
</div>
</template>
三:数据结构需要转化成 scopedSlots
自定义的插槽
原有的数据结构:
将上面的数据结构通过下面的方法进行转化。
filterTreeData(arr) {
arr.forEach((item) => {
item['scopedSlots'] = { title: 'custom' };
item.Id = item?.slots?.Id;
item.Name = item?.slots?.Name;
item.selectable = true;
item.subTitle = item.title + '(' + item.key + ')';
this.$forceUpdate();
if (item.children) {
this.filterTreeData(item.children);
}
});
},
最终转化后的数据结构如下:
此时就可以通过上面前两步的设置进行正常渲染了。
四:监听关键字的检索
4.1 节流检索关键字
//先定义一个定时器,然后在指定时间内,默认是200毫秒,如果发生变化,则清理定时器,重新定时
debounce(callback, delay = 200) {
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
callback();
}, delay);
},
4.2 input
组件作为输入框
<a-input
style="margin-top: 8px; margin-bottom: 8px"
v-model="searchValue"
placeholder="请输入关键字"
@change="onChange($event.target.value)"
allowClear
/>
4.3 监听input
的change事件
onChange(value) {
this.defaultExpandedKeys = [];
if (value) {
this.debounce(() => {
//此时需要根据value关键字,从treeData数据源中查找对应的数据,将key存放到defaultExpandedKeys数组中,就可以实现自动展开功能了。
});
} else {
this.treeData = JSON.parse(JSON.stringify(this.originTreeData));
}
},
4.4 通过XEUtiles.searchTree
实现 多层对象数组的检索
this.treeData = XEUtiles.searchTree(
this.treeData,
(item) => {
if (item.title.toLowerCase().indexOf(value.toLowerCase()) > -1) {
if (item.parent) {
this.defaultExpandedKeys.push('S-' + item.parent);
}
this.defaultExpandedKeys.push(item.key);
return true;
} else {
return false;
}
},
{ children: 'children' }
);
4.5 npm install xe-utils --save
——我这边安装的版本是3.5.6
"xe-utils": "^3.5.6"
4.6 局部页面引入xe-utils
const XEUtiles = require('xe-utils');
xe-utils使用文档说明:https://vxetable.cn/xe-utils/#/
入参:(数据源,查找条件,children的字段可以自定义)。
可以将符合条件的数据,每一层的父级都找出来。
具体的使用原理我没有研究,但是不用自己一层层遍历循环,还是很好的。
五:鼠标移入
mouseenter(item) {
this.currentId = item.key;
},
通过currentId
参数与数据源中的key
匹配,相同的则展示对应的图标。
完成!!!