參考文章:我把他的彈框單拉出來一個獨立文件作為組件方便使用,遇到一些問題記錄一下。
testComponet.vue
<template><div class="per_container"><div class="per_con_left"><div class="per_con_title">未選</div><div class="check_all"><el-checkbox:indeterminate="config.left.isIndeterminate"v-model="config.left.checkAll"@change="handleCheckAll($event, 'left')">全選/全不選</el-checkbox></div><div class="tree"><el-treeref="treeLeft":data="treeDataArr":props="propsDefault"node-key="id"show-checkbox:filter-node-method="filterNodeLeft"@check-change="handleCheckChange('left')"/></div></div><div class="operation"><el-button type="primary" @click="toRight()">移入<i class="el-icon-d-arrow-right"></i></el-button><el-button type="primary" icon="el-icon-d-arrow-left" @click="toLeft()">移除</el-button></div><div class="per_con_right"><div class="per_con_title">已選</div><div class="check_all"><el-checkbox:indeterminate="config.right.isIndeterminate"v-model="config.right.checkAll"@change="handleCheckAll($event, 'right')">全選/全不選</el-checkbox></div><div class="tree"><el-treeref="treeRight":data="treeDataArr":props="propsDefault"node-key="id"show-checkbox:filter-node-method="filterNodeRight"@check-change="handleCheckChange('right')"/></div></div></div>
</template>
<script>
export default {props: ['treeData'],mounted() {this.treeDataArr = this.treeData;this.allParentKeys = this.treeDataArr.map((item) => {return item.id;});if (this.$refs.treeLeft && this.$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.checkedKeys = this.$refs.treeRight.getCheckedKeys();this.halfCheckedKeys = this.$refs.treeRight.getHalfCheckedKeys();this.settreeDataArr(this.treeDataArr, false);this.setTreeFilter();this.$refs.treeLeft.setCheckedKeys(this.checkedKeys);this.$refs.treeRight.setCheckedKeys([]);},toRight() {this.checkedKeys = this.$refs.treeLeft.getCheckedKeys();this.halfCheckedKeys = this.$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);return data.selected;},// 遞歸設置數據選中狀態settreeDataArr(tree, type) {const setTree = (treeDataArr) => {treeDataArr.forEach((item, index) => {if (this.checkedKeys.includes(item.id)) {treeDataArr[index].selected = type;}if (item.children && item.children.length) {setTree(item.children);// 判斷半選框是否需要移動if (this.halfCheckedKeys.includes(item.id)) {if (type) {treeDataArr[index].selected = type;} else {const target = treeDataArr[index].children.find((it) => {return it.selected;});if (!target) {treeDataArr[index].selected = type;}}}}});};setTree(tree);},submitEdit() {this.$emit("permissionData", this.treeDataArr);},// 勾選樹結構時判斷是否勾選上面的全選handleCheckChange(type) {this.checkedNodes = this.$refs[this.config[type].ref].getCheckedNodes();const pIds = this.checkedNodes.filter((item) => {return !item.pId;});if (!pIds.length) {this.config[type].checkAll = false;this.config[type].isIndeterminate = false;return;}if (pIds.length === this.allParentKeys.length) {this.config[type].checkAll = true;this.config[type].isIndeterminate = false;} else {this.config[type].isIndeterminate = true;this.config[type].checkAll = false;}},// 全選handleCheckAll(value, type) {const keys = value? this.treeDataArr.map((item) => {return item.id;}): [];this.$refs[this.config[type].ref].setCheckedKeys(keys, false);}}
};
</script>
<style lang="scss" scoped>
.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.vue
<template><div><!-- 其他頁面內容 --><TestComponent :treeData="myTreeData" /></div>
</template><script>
import TestComponent from '@/views/test/test.vue';export default {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.treeDataArr = val;this.allParentKeys = this.treeDataArr.map((item) => {return item.id;});if (this.$refs.treeLeft && this.$refs.treeRight) {this.$nextTick(() => {this.setTreeFilter();});}},deep: true,},
————————————————
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。原文鏈接:https://blog.csdn.net/Error_ABC/article/details/136877442
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();// });// }},