【组件】前端ElementUi 下拉Tree树形组件 带模糊搜索自动展开高亮功能 树结构
【组件】前端ElementUi 下拉Tree树形组件 带模糊
https://live.csdn.net/v/436057
单独使用
<template>
<div>
<el-popover
style="overflow-y: auto; "
placement="bottom"
trigger="click">
<el-input
style="margin-bottom: 10px"
v-model="搜索内容"
clearable
@clear="searchHandleIptClear"
>
<el-button slot="append" icon="el-icon-search" @click="search" size="small" >搜索</el-button>
</el-input>
<!-- 树结构-->
<el-tree
style="width:auto"
ref="tree"
:props="props"
:data="data"
:check-strictly="false"
@check-change="handleCheckChange"
show-checkbox
node-key="id"
:default-expanded-keys="需要展开的节点keys"
:default-checked-keys="[]"
@node-click="handleNodeClick"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<!-- 高亮的部分-->
<span v-if="需要高亮节点数组.indexOf(data.id) !== -1" style="background-color: yellow">{{ node.label }}</span>
<!-- 不需要高亮的部分-->
<span v-else>{{ node.label }}</span>
</span>
</el-tree>
<!-- 输入框 用来显示选中的节点内容-->
<el-input slot="reference"
style="width:380px"
v-model="value.label"
placeholder="节点"
clearable
readonly
@clear="handleIptClear">
</el-input>
</el-popover>
</div>
</template>
<script>
export default {
data() {
return {
data: [{
id: 1,
label: '一级 1 A',
children: [{
id: 4,
label: '二级 1-1 张三B',
children: [{
id: 9,
label: '三级 1-1-1 李四C'
}, {
id: 10,
label: '三级 1-1-2 王五a'
}]
}]
}, {
id: 2,
label: '一级 2 赵六c',
children: [{
id: 5,
label: '二级 2-1 张三b'
}, {
id: 6,
label: '二级 2-2 李四a'
}]
}, {
id: 3,
label: '一级 3 王五D',
children: [{
id: 7,
label: '二级 3-1 赵六d'
}, {
id: 8,
label: '二级 3-2 钱七a'
}]
}],
props: {
label: 'label',
children: 'children'
},
count: 1,
value:{id:'', label: ''},
需要高亮节点数组:[],
需要展开的节点keys:[],
搜索内容:''
};
},
methods: {
searchHandleIptClear(){
this.需要高亮节点数组 = []
},
高亮模糊查询的节点递归(arr, 父节点){
if(!arr || arr.length <= 0){
return
}
let that = this
arr.forEach(item=>{
//不区分大小写匹配
if(item.label.toUpperCase().indexOf(that.搜索内容.toUpperCase()) !== -1){
console.log('搜索内容匹配', that.搜索内容, item, 父节点)
that.需要高亮节点数组.push(item.id);
if(父节点){
that.需要展开的节点keys.push(父节点.id)
}
}
if(item.children){
that.高亮模糊查询的节点递归(item.children, item)
}
})
},
/**
* 点击搜索
*/
search(){
let that = this
//1 过滤所有内容
that.需要高亮节点数组 = []
that.需要展开的节点keys = []
if(that.搜索内容){
this.高亮模糊查询的节点递归(this.data, null)
}
//3 展开匹配到的节点内容
},
// 清空输入框内容
handleIptClear(){
console.log('清空输入框内容')
//清空选中内容
this.$refs.tree.setCheckedNodes([])
this.value.id = ''
this.value.label = ''
},
/**
* 更新被选中的值
*/
updateCheck(){
const seltedNodes = this.$refs.tree.getCheckedNodes()
console.log(seltedNodes)
const ids = seltedNodes.map(n => n.id)
const labels = seltedNodes.map(n => n.label)
this.value.id = ids + ''
this.value.label = labels + ''
},
// checkbox被选中或取消选中
handleCheckChange(arg1, arg2, arg3){
console.log(arg1, arg2, arg3);
this.updateCheck()
},
// 节点被点击
handleNodeClick(arg1, arg2, arg3){
console.log('nodes:', arg1, arg2, arg3)
this.updateCheck()
},
}
};
</script>
封装为组件使用方法
引用方法
<template>
<div>
<!-- 树结构组件-->
<TreeSelector
ref="TreeSelectorRef"
:treeData="treeData"
搜索按钮名称="搜索"
提示词placeholder="请点击选择"
:是否区分大小写="false"
高亮样式Style="background-color: yellow"
>
</TreeSelector>
<el-button @click="buttonClick">设置需要高亮的节点1</el-button>
<el-button @click="buttonClick2">设置需要高亮的节点2</el-button>
<el-button @click="getCheckedKeys">获取选中节点的keys</el-button>
<el-button @click="getCheckedNodes">获取选中节点的数据</el-button>
<el-button @click="setCheckedKeys">设置选中节点</el-button>
<el-button @click="appendSetCheckedKeys">追加设置选中节点</el-button>
</div>
</template>
<script>
//引用组件
import TreeSelector from '@/components/下拉框/下拉树组件.vue'
export default {
components:{
TreeSelector
},
data() {
return {
treeData: [{
id: 1,
label: '一级 1 A',
children: [{
id: 4,
label: '二级 1-1 张三B',
children: [{
id: 9,
label: '三级 1-1-1 李四C'
}, {
id: 10,
label: '三级 1-1-2 王五a'
}]
}]
}, {
id: 2,
label: '一级 2 赵六c',
children: [{
id: 5,
label: '二级 2-1 张三b'
}, {
id: 6,
label: '二级 2-2 李四a'
}]
}, {
id: 3,
label: '一级 3 王五D',
children: [{
id: 7,
label: '二级 3-1 赵六d'
}, {
id: 8,
label: '二级 3-2 钱七a'
}]
}],
};
},
methods: {
buttonClick(){
this.$refs.TreeSelectorRef.需要高亮节点数组 = [1, 2]
},
buttonClick2(){
this.$refs.TreeSelectorRef.需要高亮节点数组 = [3]
},
/**
* 获取选中的节点数据
*/
getCheckedNodes(){
let 已选中的节点数据 = this.$refs.TreeSelectorRef.getCheckedNodes()
console.log(已选中的节点数据)
},
/**
* 获取选中的节点keys数据
*/
getCheckedKeys(){
let 已选中的节点keys = this.$refs.TreeSelectorRef.getCheckedKeys()
console.log(已选中的节点keys)
},
setCheckedKeys(){
let checkArr = [1, 2]
this.$refs.TreeSelectorRef.setCheckedKeys(checkArr)
},
/**
* 追加设置选中的节点
*/
appendSetCheckedKeys(){
let checkArr = [1]
this.$refs.TreeSelectorRef.appendSetCheckedKeys(checkArr)
}
}
};
</script>
封装为组件
<template>
<div>
<!-- 使用 Element UI 的 Popover 组件实现下拉框 -->
<el-popover
style="overflow-y: auto; "
placement="bottom"
trigger="click">
<!-- 输入框用于搜索树结构中的节点 -->
<el-input
style="margin-bottom: 10px"
v-model="searchContent"
clearable
@clear="searchHandleIptClear"
>
<el-button slot="append" icon="el-icon-search" @click="search" size="small" >{{搜索按钮名称}}</el-button>
</el-input>
<!-- 树结构展示数据 -->
<el-tree
style="width:auto"
ref="tree"
:props="props"
:data="treeData"
:check-strictly="false"
@check-change="handleCheckChange"
show-checkbox
node-key="id"
:default-expanded-keys="需要展开的节点keys"
@node-click="handleNodeClick"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<!-- 高亮的部分-->
<span v-if="需要高亮节点数组 && 需要高亮节点数组.indexOf(data.id) !== -1" :style="高亮样式Style">{{ node.label }}</span>
<!-- 不需要高亮的部分-->
<span v-else>{{ node.label }}</span>
</span>
</el-tree>
<!-- 输入框 用来显示选中的节点内容-->
<el-input slot="reference"
style="width:380px"
v-model="value.label"
:placeholder="提示词placeholder"
clearable
readonly
@clear="handleIptClear">
<!-- 清除按钮-->
<i
slot="suffix"
@click="IptClearClick"
style="margin-top: 11px; cursor: pointer"
class="el-icon-circle-close clear-button"></i>
</el-input>
</el-popover>
</div>
</template>
<script>
export default {
name: 'TreeSelector', // 组件名称
/**
* 属性
*/
props: {
// 树结构的数据源
treeData: {
type:Array,
required:true,
default:()=>[]
},
高亮样式Style: {
type:String,
default:()=>'background-color: yellow'
},
是否区分大小写: {
type:Boolean,
default:()=>false
},
//搜索按钮名称
搜索按钮名称:{
type:String,
default:()=>'搜索'
},
//提示词placeholder
提示词placeholder:{
type:String,
default:()=>'点击选择'
},
},
data() {
return {
需要高亮节点数组:[],
// 已选中的节点keys:[],
需要展开的节点keys:[],
searchContent:'',
props: {
label: 'label',
children: 'children'
},
value:{id:'', label: ''},
};
},
mounted() {
},
methods: {
//清空搜索框内容事件
searchHandleIptClear(){
this.需要高亮节点数组 = []
},
高亮模糊查询的节点递归(arr, 父节点){
if(!arr || arr.length <= 0){
return
}
let that = this
arr.forEach(item=>{
let labelTmp = item.label;
let searchContentTmp = that.searchContent;
//不区分大小写匹配
if(that.是否区分大小写 === false){
labelTmp = labelTmp.toUpperCase()
searchContentTmp = searchContentTmp.toUpperCase()
}
if(labelTmp.indexOf(searchContentTmp) !== -1){
// console.log('搜索内容匹配', that.searchContent, item, 父节点)
that.需要高亮节点数组.push(item.id);
if(父节点){
that.需要展开的节点keys.push(父节点.id)
}
}
if(item.children){
that.高亮模糊查询的节点递归(item.children, item)
}
})
},
/**
* 点击搜索
*/
search(){
let that = this
//1 过滤所有内容
that.需要高亮节点数组 = []
that.需要展开的节点keys = []
if(that.searchContent){
this.高亮模糊查询的节点递归(this.treeData, null)
}
},
IptClearClick(event){
// console.log(event)
// event.preventDefault();
this.handleIptClear()
},
// 清空输入框内容
handleIptClear(){
// console.log('清空输入框内容')
//清空选中内容
this.$refs.tree.setCheckedNodes([])
this.value.id = ''
this.value.label = ''
},
/**
* 更新被选中的值
*/
updateCheck(){
const seltedNodes = this.getCheckedNodes()
// console.log(seltedNodes)
const ids = seltedNodes.map(n => n.id)
const labels = seltedNodes.map(n => n.label)
this.value.id = ids + ''
this.value.label = labels + ''
},
// checkbox被选中或取消选中
handleCheckChange(arg1, arg2, arg3){
// console.log(arg1, arg2, arg3);
this.updateCheck()
},
// 节点被点击
handleNodeClick(arg1, arg2, arg3){
// console.log('nodes:', arg1, arg2, arg3)
this.updateCheck()
},
/**
* 获取已选中的节点集合
*/
getCheckedNodes(){
return this.getTreeRef().getCheckedNodes();
},
/**
* 获取已选中的节点keys集合
*/
getCheckedKeys(){
return this.getCheckedNodes().map(n => n.id);
},
/**
* 追加设置选中的节点
* @param arr
*/
appendSetCheckedKeys(arr){
let 已选中的keys = this.getCheckedKeys()
const mergedArray = [...已选中的keys, ...arr];
const mergedSet = new Set(mergedArray);
this.setCheckedKeys(Array.from(mergedSet))
},
/**
* 设置选中的节点
* @param arr
*/
setCheckedKeys(arr){
this.getTreeRef().setCheckedKeys(arr)
},
/**
* 获取tree ref
* https://element.eleme.cn/#/zh-CN/component/tree
* @returns {HTMLElement}
*/
getTreeRef(){
return this.$refs.tree;
}
}
};
</script>