一、关键代码
<template><div><!-- 左侧待选列表 --><div class="left-box"><p>待选列表</p><el-input placeholder="输入关键词过滤" v-model="leftFilterText" clearable/><el-treeref="treeLeft":data="leftData"show-checkboxnode-key="id"props="defaultProps":load="loadNode"lazy:filter-node-method="filterNode" ></el-tree></div><!-- 穿梭按钮 --><div class="oper-box"><el-button circle type="primary" icon="el-icon-arrow-left" @click="removeData"></el-button><el-button circle type="primary" icon="el-icon-arrow-right" @click="addData"></el-button></div><div class="right-box"><p>已选列表</p><el-input placeholder="输入关键词过滤" v-model="rightFilterText" clearable/><el-treeref="treeRight":data="rightData"show-checkboxnode-key="id"props="defaultProps":filter-node-method="filterNode" ></el-tree></div></div>
</template><script>data(){return {checkAll: false,leftFilterText: '',rightFilterText: '',defaultProps: {chilren: 'children',label: 'labelName', // 适配后端下发的数据字段名isLeaf: 'leaf', // leaf 字段判断节点是否为叶子节点// 配置禁选的节点disabled: function(data, node) {// 如这里配置父节点、带有disable属性的节点禁选if('children' in data || data.disable) {return true;} else {return false;}}},leftData: [],rightData: []}},watch: {leftFilterText(val) {this.$refs.treeLeft.filter(val);},rightFilterText(val) {this.$refs.treeRight.filter(val);}},methods: {// 根据关键词过滤节点filterNode(value, data) {if(!value) return true;// labeName 为defaultProps中配置的label值,未配置默认为labelreturn data.labeName.indexOf(value) !== -1;},// 懒加载出树结构的最后一层节点async loadNode(node, resolve) {if(node.level === 0) {return resolve(node.data); // 顶层数据默认展示} else {if(node.data.children && node.data.children.length > 0) {return resolve(node.data.children);} else { // 最后一层数据,异步懒加载let tempData = await this.getDynamicData(node.data.id);return resolve(tempData);}}},// 获取数据接口getDynamicData(id) {},// 移除节点removeData() {// 右侧选中节点let removeKeys = this.$refs.treeRight.getCheckedKeys();this.rightData = this.rightData.filter(item => !removeKeys.includes(item.id));// 左侧:仅保留右侧列表中有的数据为勾选状态let leftCheckKeys = this.rightData.map(item => item.id);this.$refs.treeLeft.setCheckedKeys(leftCheckKeys);},// 添加节点removeData() {// 获取左侧选中节点,作为右侧的数据let checkNodes = this.$refs.treeLeft.getCheckedNodes();let checkKeys = this.$refs.treeLeft.getCheckedKeys();this.rightData = checkNodes;},}
</script>
🎨 过滤节点函数:filterNode
1、watch 监听关键词;filterNode 必须有返回值,否则数据显示不出来;
2、关键词不为空时,函数的返回值 data.labeName.indexOf(value) !== -1; 其中 labeName 为defaultProps中配置的label值,未配置默认为label
🎨 异步加载函数:loadNode
根据 node.level 去匹配数据层级,判断是否需要调用接口获取数据
🎨 样式自定义
二、最终效果:(效果图仅供参考)
(1) 左侧列表为树形结构,且最后一级节点懒加载;(数据量大时,可以有效提高加载速度)
(2)右侧选中的列表无树形结构,为左侧选中的所有节点