element-ui Tree 树形控件 过滤保留子级并获取过滤后的数据 多选改单选
element
A Vue.js 2.0 UI Toolkit for Web
项目地址:https://gitcode.com/gh_mirrors/eleme/element
免费下载资源
·
本示例基于vue2 + element-ui
element-ui 的官网demo是只保留到过滤值一级的,并不会保留其子级
目标
1、Tree 树形控件 保留过滤值的子级
2、在第一次过滤数据的基础上进行第二次过滤
3、Tree 树形控件 多选改为单选,且只有最末端子级可以选择
不足之处
过滤时无法指定过滤哪一级的数据(保留其子级数据)
实际场景需求
- 第一次过滤时只过滤第三级数据
- 第二次过滤时在第一次过滤的基础上过滤最后一级
1 暂时无法实现(如果有大佬用前端方法实现,记得call我!)
2 过滤最后一级可以实现(代码随后附上)
先看效果
1、2
3 多选改单选效果
Tree 树形控件 保留过滤值的子级
<el-tree
class="filter-tree"
node-key="id"
:data="treeData"
:props="defaultProps"
default-expand-all
show-checkbox
@check-change="handleCheckChange"
:filter-node-method="filterNode"
ref="tree">
</el-tree>
// 对树节点进行筛选时执行的方法
filterNode (value, data, node) {
let parentNode = node.parent; // 父级node
let labels = [node.label]; // 当前node的名字
let level = 1; // 层级
while (level < node.level) {
labels = [...labels, parentNode.label]; // 当前node名字,父级node的名字
parentNode = parentNode.parent;
level++;
}
return labels.some((d) => d.indexOf(value) !== -1);
},
在第一次过滤数据的基础上进行第二次过滤
1、下载插件库
npm install -S circular-json
2、在使用页面引入
import CircularJSON from 'circular-json'
3、代码应用
<template>
<div class="about-container">
<h1>获取过滤后的tree数据</h1>
<el-input
clearable
placeholder="第一次过滤"
@keyup.enter.native="handleFilter1"
v-model="firstText">
</el-input>
<el-input
style="margin-top: 10px;"
clearable
placeholder="第二次过滤"
@keyup.enter.native="handleFilter2"
v-model="secondText">
</el-input>
<el-button @click="handleFilter1(),handleFilter2()" type="primary" icon="el-icon-search">搜索</el-button>
<div>
<el-tree
class="filter-tree"
node-key="id"
:data="treeData"
:props="defaultProps"
default-expand-all
show-checkbox
@check-change="handleCheckChange"
:filter-node-method="filterNode"
ref="tree">
</el-tree>
</div>
</div>
</template>
<script>
// 在使用的组件内引入
import CircularJSON from 'circular-json'
export default {
data() {
return {
// 第一次过滤
firstText: '',
// 第二次过滤
secondText:'',
// tree控件的渲染值
treeData: [{
id: 1,
label: '一级1',
children: [{
id: 4,
label: '二级1-1',
children: [{
id: 9,
label: '三级1-1-1',
children: [{
id:91,
label: '四级1'
},{
id:92,
label: '四级2'
}]
}, {
id: 10,
label: '三级1-1-2'
}]
}]
}, {
id: 2,
label: '一级2',
children: [{
id: 5,
label: '二级2-1'
}, {
id: 6,
label: '二级2-2'
}]
}, {
id: 3,
label: '一级',
children: [{
id: 7,
label: '二级3-1'
}, {
id: 8,
label: '二级3-2'
},{
id: 82,
label: '四级3'
}]
},{
id: 31,
label: '奇迹',
children: [{
id: 71,
label: '奇迹1'
}, {
id: 81,
label: '奇迹2'
}]
}],
defaultProps: {
children: 'children',
label: 'label'
},
// tree的原版备份数据
deepCloneTreeData:[],
// 第一次过滤后tree控件渲染数据
firstFilterdata:[],
}
},
mounted() {
this.deepClone(this.treeData).then((res)=>{
this.deepCloneTreeData = res;
})
},
methods: {
// 第一次过滤
handleFilter1() {
// 第一次过滤时没有输入值,即用tree控件的原始值
if(!this.firstText){
this.treeData = this.deepCloneTreeData;
this.firstFilterdata = this.deepCloneTreeData;
return
}
this.$refs.tree.filter(this.firstText)
this.firstFilterdata = this.getFilterData();
},
// 第二次过滤
handleFilter2() {
// 基于第一次过滤出来的数据
if(this.firstFilterdata.length > 0) this.treeData = this.firstFilterdata;
this.$nextTick(()=>{
this.$refs.tree.filter(this.secondText);
})
},
// 对树节点进行筛选时执行的方法
filterNode (value, data, node) {
let parentNode = node.parent; // 父级node
let labels = [node.label]; // 当前node的名字
let level = 1; // 层级
while (level < node.level) {
labels = [...labels, parentNode.label]; // 当前node名字,父级node的名字
parentNode = parentNode.parent;
level++;
}
return labels.some((d) => d.indexOf(value) !== -1);
},
// tree 的选择事件
handleCheckChange(data, checked, indeterminate) {
const arr = this.$refs.tree.getCheckedKeys()
},
// 需要获取过滤后的 Tree组件数据
getFilterData() {
const rootData = this.$refs.tree.root;
if (rootData.visible) {
const childNodesStr = CircularJSON.stringify(rootData.childNodes);
const childNodes = CircularJSON.parse(childNodesStr);
const filterData = this.recursionNodes(childNodes);
return filterData;
}
},
/**
* 递归遍历数据
* 这里解释一下为什么要用CircularJSON这个插件,因为element tree
* node数据存在一个对象里的子项存在循环引用,存在循环引用的对象
*/
recursionNodes(childNodes) {
const nodes = childNodes;
const result = [];
for (const item of nodes) {
if (item.visible) {
result.push(item.data);
}
if (item.childNodes && item.childNodes.length) {
const tempResult = this.recursionNodes(item.childNodes);
item.data.children = tempResult;
}
}
return result;
},
/**
* 深拷贝
*/
deepClone(obj){
return new Promise((resolve) => {
const { port1,port2 } = new MessageChannel();
port1.postMessage(obj);
port2.onmessage = (msg) => {
resolve(msg.data)
}
})
}
},
}
</script>
只过滤最后一级
/**
* 数据处理
*
* 需要对每级数据进行level标记,方便后续过滤
*/
treeData: [{
id: 1,
label: '一级1',
level:1,
children: [{
id: 4,
label: '二级1-1',
level:2,
children: [{
id: 9,
label: '三级1-1-1',
level:3,
children: [{
id:91,
label: '四级1',
level:4,
},{
id:92,
label: '四级2',
level:4,
}]
}, {
id: 10,
label: '三级1-1-2',
level:3,
}]
}]
}, {
id: 2,
label: '一级2',
level:1,
children: [{
id: 5,
label: '二级2-1',
level:2,
}, {
id: 6,
label: '二级2-2',
level:2,
}]
}, {
id: 3,
label: '一级',
level:1,
children: [{
id: 7,
label: '二级3-1',
level:2,
}, {
id: 8,
label: '二级3-2',
level:2,
},{
id: 82,
label: '四级3',
level:2,
}]
},{
id: 31,
label: '奇迹',
level:1,
children: [{
id: 71,
label: '奇迹1',
level:2,
}, {
id: 81,
label: '奇迹2',
level:2,
}]
}]
// 对树节点进行筛选时执行的方法
filterNode(value, data, node) {
/**
* 筛选最后一级可用
*
* [4].includes(data.level
* [] 中写入最后一级的level值
*/
if ([4].includes(data.level) && data.label.indexOf(value) !== -1) {
console.log(value,data,node,'4-------',data.label.indexOf(value));
let parentNode = node.parent; // 父级node
let labels = [node.label]; // 当前node的名字
let level = 1; // 层级
while (level < node.level) {
// console.log(labels,'labels');
labels = [...labels, parentNode.label]; // 当前node名字,父级node的名字
parentNode = parentNode.parent;
level++;
}
return labels.some((d) => d.indexOf(value) !== -1);
}
},
Element tree组件 多选改为单选
<el-tree
class="treeRadio"
check-strictly
@check-change="deptCheck"
deptCheck(data, check, childCheck) {
if(check){
this.$refs.tree.setCheckedNodes([data]);
}
}
// css 让父级不显示checkbox
::v-deep .el-tree .el-tree-node .is-leaf + .el-checkbox .el-checkbox__inner{
display: inline-block;
}
::v-deep .el-tree .el-tree-node .el-checkbox .el-checkbox__inner{
display: none;
}
::v-deep .treeRadio .el-checkbox__inner{
border-radius: 50%;
transform: scale(1.2);
}
// 样式改为单选框的样式
::v-deep .treeRadio .el-checkbox__inner{
border-radius: 50%;
transform: scale(1.2);
}
GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45
7 个月前
a07f3a59
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update table.md
* Update transition.md
* Update popover.md 7 个月前
更多推荐
已为社区贡献2条内容
所有评论(0)