ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

前端笔记之el-tree结合el-tree-transfer实现穿梭框里展示树形数据

前端笔记之el-tree结合el-tree-transfer实现穿梭框里展示树形数据 参考文章我把他的弹框单拉出来一个独立文件作为组件方便使用遇到一些问题记录一下。testComponet.vuetemplatedivclassper_containerdivclassper_con_leftdivclassper_con_title未选/divdivclasscheck_allel-checkbox:indeterminateconfig.left.isIndeterminatev-modelconfig.left.checkAllchangehandleCheckAll($event, left)全选/全不选/el-checkbox/divdivclasstreeel-treereftreeLeft:datatreeDataArr:propspropsDefaultnode-keyidshow-checkbox:filter-node-methodfilterNodeLeftcheck-changehandleCheckChange(left)//div/divdivclassoperationel-buttontypeprimaryclicktoRight()移入iclassel-icon-d-arrow-right/i/el-buttonel-buttontypeprimaryiconel-icon-d-arrow-leftclicktoLeft()移除/el-button/divdivclassper_con_rightdivclassper_con_title已选/divdivclasscheck_allel-checkbox:indeterminateconfig.right.isIndeterminatev-modelconfig.right.checkAllchangehandleCheckAll($event, right)全选/全不选/el-checkbox/divdivclasstreeel-treereftreeRight:datatreeDataArr:propspropsDefaultnode-keyidshow-checkbox:filter-node-methodfilterNodeRightcheck-changehandleCheckChange(right)//div/div/div/templatescriptexportdefault{props:[treeData],mounted(){this.treeDataArrthis.treeData;this.allParentKeysthis.treeDataArr.map((item){returnitem.id;});if(this.$refs.treeLeftthis.$refs.treeRight){this.$nextTick((){this.setTreeFilter();});}},created(){// this.treeDataArr this.treeData;// this.allParentKeys this.treeDataArr.map((item) {// return item.id;// });// if (this.$refs.treeLeft this.$refs.treeRight) {// this.$nextTick(() {// this.setTreeFilter();// });// }},data(){return{propsDefault:{label:name},isIndeterminateL:false,isIndeterminateR:false,checkAllLeft:false,checkAllRight:false,treeDataArr:[],checkedKeys:[],halfCheckedKeys:[],checkedNodes:[],config:{left:{isIndeterminate:false,checkAll:false,ref:treeLeft},right:{isIndeterminate:false,checkAll:false,ref:treeRight}}};},methods:{setTreeFilter(){this.$refs.treeLeft.filter();this.$refs.treeRight.filter();},toLeft(){this.checkedKeysthis.$refs.treeRight.getCheckedKeys();this.halfCheckedKeysthis.$refs.treeRight.getHalfCheckedKeys();this.settreeDataArr(this.treeDataArr,false);this.setTreeFilter();this.$refs.treeLeft.setCheckedKeys(this.checkedKeys);this.$refs.treeRight.setCheckedKeys([]);},toRight(){this.checkedKeysthis.$refs.treeLeft.getCheckedKeys();this.halfCheckedKeysthis.$refs.treeLeft.getHalfCheckedKeys();this.settreeDataArr(this.treeDataArr,true);this.setTreeFilter();this.$refs.treeRight.setCheckedKeys(this.checkedKeys);this.$refs.treeLeft.setCheckedKeys([]);},filterNodeLeft(value,data){console.log(filterNodeLeft,data);return!data.selected;},filterNodeRight(value,data){console.log(filterNodeRight,data);returndata.selected;},// 递归设置数据选中状态settreeDataArr(tree,type){constsetTree(treeDataArr){treeDataArr.forEach((item,index){if(this.checkedKeys.includes(item.id)){treeDataArr[index].selectedtype;}if(item.childrenitem.children.length){setTree(item.children);// 判断半选框是否需要移动if(this.halfCheckedKeys.includes(item.id)){if(type){treeDataArr[index].selectedtype;}else{consttargettreeDataArr[index].children.find((it){returnit.selected;});if(!target){treeDataArr[index].selectedtype;}}}}});};setTree(tree);},submitEdit(){this.$emit(permissionData,this.treeDataArr);},// 勾选树结构时判断是否勾选上面的全选handleCheckChange(type){this.checkedNodesthis.$refs[this.config[type].ref].getCheckedNodes();constpIdsthis.checkedNodes.filter((item){return!item.pId;});if(!pIds.length){this.config[type].checkAllfalse;this.config[type].isIndeterminatefalse;return;}if(pIds.lengththis.allParentKeys.length){this.config[type].checkAlltrue;this.config[type].isIndeterminatefalse;}else{this.config[type].isIndeterminatetrue;this.config[type].checkAllfalse;}},// 全选handleCheckAll(value,type){constkeysvalue?this.treeDataArr.map((item){returnitem.id;}):[];this.$refs[this.config[type].ref].setCheckedKeys(keys,false);}}};/scriptstylelangscssscoped.per_container{display:flex;height:500px;justify-content:space-between;align-items:center;}.per_con_left, .per_con_right{width:45%;height:100%;}.operation{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;}.operation .el-button{margin-left:0;margin-bottom:10px;}.per_con_title{height:42px;line-height:26px;border-radius:8px 8px 0 0;padding:8px;align-self:stretch;background:#f2f6f9;font-size:16px;box-sizing:border-box;border:1px solid #d8d8d8;font-weight:700;text-align:left;}.check_all{height:42px;line-height:42px;padding:0 5px;border:1px solid #d8d8d8;border-top:none;text-align:left;}.tree{height:calc(100% - 82px);border:1px solid #d8d8d8;border-top:none;overflow:auto;}/style思路1思路二利用elementUI的filter API对选中节点进行筛选左侧筛选出未选中的右侧筛选出选中的用的还是同一棵树用一个属性来区分是否选择好处是子节点选中父节点会跟随保存不用重新构建树结构。2通过监听treeData值变化调用setTreeFilter也就是this.$refs.treeLeft.filter(); this.$refs.treeRight.filter();里的filter 方法filter 是 el-tree 组件用于动态过滤树节点配合 filter-node-method 属性可以实现节点过滤自定义左右侧树过滤的规则分别是是filterNodeLeft(value, data) { return !data.selected;},和filterNodeRight(value, data) {return data.selected;},是否被选中左移右移来设置selected属性testIndex.vuetemplatediv!--其他页面内容--TestComponent:treeDatamyTreeData//div/templatescriptimportTestComponentfrom/views/test/test.vue;exportdefault{components:{TestComponent},data(){return{myTreeData:[// 这里放置你的树形数据{id:1,name:父节点1,children:[{id:2,name:子节点1}]}]};},// ... existing code ...};/script关于监听treeData变化后给树赋数据这里遇到问题我把原文监听treeData对树进行初始化一开始写在created里导致左右都有树然后改为mounted就没有这个问题。原因操作DOM元素用mounted依赖 DOM 元素 setTreeFilter 方法可能依赖于this.$refs.treeLeft和this.$refs.treeRight这两个 DOM 引用。在 created 阶段DOM 元素还未挂载this.$refs无法正确获取到对应的 DOM 元素从而导致过滤逻辑无法正常执行。而在 mounted 阶段DOM 元素已经挂载完成this.$refs可以正常获取到对应的 DOM 元素过滤逻辑就能正常工作了。treeData:{handler(val){this.treeDataArrval;this.allParentKeysthis.treeDataArr.map((item){returnitem.id;});if(this.$refs.treeLeftthis.$refs.treeRight){this.$nextTick((){this.setTreeFilter();});}},deep:true,},———————————————— 版权声明本文为博主原创文章遵循CC4.0BY-SA版权协议转载请附上原文出处链接和本声明。原文链接https://blog.csdn.net/Error_ABC/article/details/136877442created(){// this.treeDataArr this.treeData;// this.allParentKeys this.treeDataArr.map((item) {// return item.id;// });// if (this.$refs.treeLeft this.$refs.treeRight) {// this.$nextTick(() {// this.setTreeFilter();// });// }},
返回列表