需求
由于element中的穿梭框不能實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)數(shù)據(jù)的使用,所以利用Tree進(jìn)行重新封裝.
效果如圖:
代碼實(shí)現(xiàn)
1.結(jié)構(gòu)
<template>
<div class="transferTreeBox">
<!-- 左側(cè)待選內(nèi)容 -->
<div class="SelectBox">
<div
class="boxTitle"
@click="clickAllSelect"
>
全選 >
</div>
<div class="boxCenter">
<el-tree
ref="beforeTree"
:data="cascaderData"
:props="defaultProps"
show-checkbox
:filter-node-method="beforeFilterNode"
:accordion="true"
node-key="nodeCode"
/>
</div>
</div>
<!-- 中間穿梭按鈕 -->
<div class="transferBtn">
<div
class="pickBtn"
@click="towardsRight"
>
>>
</div>
<div
class="pickBtn"
@click="towardsLeft"
>
<<
</div>
</div>
<!-- 右側(cè)已選內(nèi)容 -->
<div class="SelectBox">
<div
class="boxTitle"
@click="clickCancelAllSelect"
>
< 取消全選
</div>
<div class="boxCenter">
<el-tree
ref="afterTree"
:data="cascaderData"
:props="defaultProps"
show-checkbox
:filter-node-method="afterFilterNode"
node-key="nodeCode"
/>
</div>
</div>
</div>
</template>
2.邏輯
<script>
export default {
props: ["cascaderData"], // 班級(jí)的樹(shù)形結(jié)構(gòu)數(shù)據(jù)
data () {
return {
defaultProps: {
children: "children",
label: "label"
},
beforeKeyarr: [],
afterKeyarr: []
};
},
mounted () {
// 打開(kāi)彈窗清空右側(cè)樹(shù)形框
this.$refs.afterTree.filter();
},
methods: {
// 將組件的默認(rèn)選中清除
keyClear(str){
// 首先獲取node
let node = this.$refs[str].getNode(this.cascaderData[0].nodeCode).parent;
this.clearClickRecursion(node.childNodes);
},
// 清除樹(shù)形默認(rèn)選中的層級(jí)遞歸
clearClickRecursion(data){
data.forEach(val => {
val.checked = false;
if (val.childNodes && val.childNodes.length>0){
this.clearClickRecursion(val.childNodes);
}
});
},
// 點(diǎn)擊向右穿梭
towardsRight(){
let currentBeforeKeyarr = this.$refs.beforeTree.getCheckedNodes(true);
// ES6語(yǔ)法.清除數(shù)組內(nèi)相同的對(duì)象
let arr = this.beforeKeyarr.filter(item => !currentBeforeKeyarr.some(ele => ele.value === item.value));
this.beforeKeyarr = arr;
this.beforeKeyarr = [...this.beforeKeyarr,...currentBeforeKeyarr];
this.shuttle();
},
// 點(diǎn)擊向左穿梭
towardsLeft(){
this.afterKeyarr = this.$refs.afterTree.getCheckedNodes(true);
let arr = this.beforeKeyarr.filter(item => !this.afterKeyarr.some(ele => ele.value === item.value));
this.beforeKeyarr = arr;
this.shuttle();
},
// 穿梭
async shuttle(){
let str = "";
this.beforeKeyarr.forEach(item => {
if (str) {
str = `${str},${item.value}`;
} else {
str = item.value;
}
});
this.keyClear("beforeTree");
this.keyClear("afterTree");
await this.$refs.beforeTree.setCheckedKeys([]);
await this.$refs.afterTree.setCheckedKeys([]);
this.$refs.beforeTree.filter(str);
this.$refs.afterTree.filter(str);
this.$emit("getcascaderlist",this.beforeKeyarr);
},
// 過(guò)濾
beforeFilterNode(value, data) {
if (!value) {
return true;
}
return value.indexOf(data.value) < 0;
},
afterFilterNode(value, data){
if (!value) {
return false;
}
return value.indexOf(data.value) !== -1;
},
// 點(diǎn)擊全選
clickAllSelect(){
this.$refs.beforeTree.setCheckedNodes(this.cascaderData);
this.towardsRight();
},
// 點(diǎn)擊取消全選
clickCancelAllSelect(){
this.$refs.afterTree.setCheckedNodes(this.cascaderData);
this.towardsLeft();
}
}
};
</script>
3.樣式
<style lang="scss" scoped>
.transferTreeBox{
display: flex;
width: 590px;
justify-content: space-around;
.SelectBox{
border: 1px solid #ccc;
height: 270px;
width: 200px;
color: #fff;
position: relative;
.boxTitle{
background: #a0cfff;
height: 30px;
line-height: 30px;
text-align: center;
border-bottom: 1px solid #ccc;
cursor: pointer;
}
.boxCenter{
height: 100%;
width: 100%;
max-height: 239px;
overflow-y: scroll;
}
}
.transferBtn{
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.pickBtn{
height: 30px;
width: 50px;
background: #a0cfff;
color: #fff;
font-weight: 700;
font-size: 20px;
border-radius: 5px;
margin-top: 10px;
text-align: center;
line-height: 30px;
cursor: pointer;
}
}
}
</style>