项目需求:
1,穿梭框中为树形列表,a-transfer + a-table(table 数据为treeData);
2,父节点为多选,子节点是单选
穿梭框左边的列表需要满足父子节点联动:勾选子节点时默认选中父节点,选中父节点时默认勾选子节点(初次默认选中第1个子节点,否则选中上次勾选的子节点),取消勾选父节点同时取消勾选的子节点;
穿梭到右边的列表不需要父子节点联动,穿梭过去时需要保留子节点选中状态,同时父节点清空选中状态。
代码如下:
<a-transfer
titles="标题"
:data-source="configData"
:target-keys="targetKeys"
:show-search="true"
:filter-option="(inputValue, item) => item.title.indexOf(inputValue) !== -1"
:show-select-all="false"
pagination
@change="onChange"
>
<template
slot="children"
slot-scope="{
props: { direction, filteredItems, selectedKeys, disabled: listDisabled },
on: { itemSelectAll, itemSelect },
}"
>
<a-table
:row-selection="getRowSelection({ disabled: listDisabled,
selectedKeys,
itemSelectAll,
itemSelect,
findGoalRow })"
:columns="direction === 'left' ? leftColumns : rightColumns"
:data-source="filteredItems"
size="small"
>
<template slot="isNeed" slot-scope="text, record">
<a-radio-group name="radioGroup" v-model="record.isNeed" :default-value="record.isNeed">
<a-radio :value="true"> 是 </a-radio>
<a-radio :value="false"> 否 </a-radio>
</a-radio-group>
<span> {{text}}</span>
</template>
---------------子节点插槽--------------------
<template slot="expandedRowRender" slot-scope="row, index" >
<a-table
disabled
v-if="row.childrenNode.length > 0"
:columns="innerColumns"
:dataSource="row.childrenNode"
:rowSelection="{
selectedRowKeys: row.checkedKey || [],
hideDefaultSelections: true,
onChange: (selectedRowKeys, selectedRows) =>
onSelectChangeInner(selectedRowKeys, selectedRows, row, index, itemSelect),
type: 'radio'}"
:pagination="false"
:showHeader="false" />
</template>
</a-table>
</template>
</a-transfer>
---------------获取,处理data数据--------
this.configData = res.result.map(obj => {
if(obj.children){
obj.children.forEach((t,i)=>{
obj.children[i].key = obj.children[i].id //列表数据必须设置唯一key
})
}
return {
key: obj.id,
id: obj.id,
title: obj.name,
disabled: false,
isNeed: false,
description: '',
childrenNode: obj.children || [], //取消树形数据默认效果
checkedKey: obj.checkedKey || [], //选中的子节点key
firstCheckedKey: obj.children ? obj.children[0].key : '', //第一个子节点key
}
});
this.configDataKeys = this.configData.map(t=>t.key)
---------------methods-------------------
import difference from 'lodash/difference';
//1,穿梭框点击事件
onChange(nextTargetKeys,direction) {
console.log('onChange--',this.targetKeys,nextTargetKeys)
const leftDataList = difference(this.configDataKeys,nextTargetKeys)
if(direction === 'left'){
//穿梭到左边:增加字段标识,清空子节点选中状态
leftDataList.forEach(t=>{
let row = this.findGoalRow(t)
if(row.length > 0){
row[0].checkedKey[0] = ''
row[0].direction = direction
}
})
}else{
//穿梭到右边:增加字段标识
nextTargetKeys.forEach(t=>{
let row = this.findGoalRow(t)
if(row.length > 0){
row[0].direction = direction
}
})
}
this.targetKeys = nextTargetKeys;
},
//2,父节点全选,选中,取消选中事件
getRowSelection({ disabled, selectedKeys, itemSelectAll, itemSelect, findGoalRow }) {
console.log('主表勾选--',selectedKeys)
return {
onSelectAll(selected, selectedRows) {
const treeSelectedKeys = selectedRows
.filter(item => !item.disabled)
.map(({ key }) => key);
const diffKeys = selected
? difference(treeSelectedKeys, selectedKeys)
: difference(selectedKeys, treeSelectedKeys);
//全选时:默认选中子节点
//取消全选时:取消选中的子节点
diffKeys.forEach(t=>{
let row = findGoalRow(t)
if(row.length > 0){
if(row[0].direction !== 'right'){
row[0].checkedKey[0] = selected ? (row[0].beforeCheckedKey || row[0].firstCheckedKey) : ''
}
}
})
itemSelectAll(diffKeys, selected);
},
onSelect({ key }, selected) {
console.log('onSelect--',key,selected,selectedKeys)
let selectedRow = findGoalRow(key)
if(!selected){
let index = selectedKeys.indexOf(key)
console.log('index',index,'selectedKeys',selectedKeys)
if(index !== -1){
selectedKeys.splice(index,1)
}
//取消勾选父节点的同时取消子节点的勾选
if(selectedRow[0].direction !== 'right'){
selectedRow[0].checkedKey = []
}
}else{
if(!selectedKeys.includes(key)){
selectedKeys.push(key)
}
//勾选父节点,如果子节点没有勾选则默认选中第一条,如果子节点上次有勾选则恢复上次勾选
selectedRow[0].checkedKey[0] = selectedRow[0].beforeCheckedKey || selectedRow[0].firstCheckedKey
}
itemSelect(key, selected);
},
selectedRowKeys: selectedKeys,
};
},
//3,子节点选中事件(子节点为单选,只能选中,其父节点取消选中时则子节点也取消选中)
onSelectChangeInner(selectedRowKey, selectionRow, row, index, itemSelect){
console.log('单选',selectedRowKey, selectionRow,row.key,index)
this.$set(row, 'checkedKey', selectedRowKey);
this.$set(row, 'beforeCheckedKey', selectedRowKey[0]);
//左边列表:父子节点勾选联动
//右边列表:父子节点勾选不联动
if(row.direction !== 'right'){
itemSelect(row.key, true)
}
},
//4,根据key找对应的row
findGoalRow(key){
return this.configData.filter(t=>t.key === key)
},