效果大概如下,可以自己拿代碼試試,這個現在是隻能拿到選中的添加到右邊,并且會覆寫右邊的資料,再研究下追加到右邊,有需要的可以自己再封裝成通用元件
樹結構穿梭框下篇,可追加資料
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNiZpdmL3kzM3ETNzkDMyIzMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.gif)
import React, { Component } from 'react';
import { Tree, Input, Button } from 'antd';
// import requset from '@/utils/request';
import { NuCard } from '@cbay/cbay-ui';
import { cloneDeep } from 'lodash';
const { Search } = Input;
//扁平後資料
let arr = [];
class TransferTree extends Component {
state = {
treeData: [],
expandedKeys: [],
searchValue: '',
autoExpandParent: true,
loading: false,
rightTree: [],
rightTreeCopy: [],
checkedKeysLeft: [],
leftBtnDisabled: true,
rightBtnDisabled: true
};
componentDidMount() {
//請求樹結構
//如果沒有給父節點key,那就給每個子節點設定父節點key
const newDATA = cloneDeep(DATA);
this.setParent(newDATA);
// console.log(DATA);
//扁平資料
this.setnode(newDATA);
// console.log(arr);
}
//1設定父節點id
setParent = treeData => {
treeData.map(t => {
if (t.children && t.children.length) {
t.children.map(c => {
c.parentKey = t.key;
});
this.setParent(t.children);
} else {
return;
}
});
};
//2扁平資料
setnode = c => {
c.map(item => {
arr.push(item);
item.children && this.setnode(item.children);
});
};
onSelect = (selectedKeys, info) => {
console.log(info);
const { type, eventKey } = info.node.props;
this.setState({
selected: {
type,
id: eventKey
}
});
};
checked = (checkedkeys, node) => {
const { halfCheckedKeys } = node || {};
//設定左邊複選框選中的key
this.setState({
checkedKeysLeft: {
checked: checkedkeys,
halfChecked: halfCheckedKeys
}
});
//
let checkedAllLeftKey = checkedkeys.concat(halfCheckedKeys);
// const rightTreeCopy = this.ListToTree(selectValue);
const rightTreeCopy = this.ListToTree(checkedAllLeftKey);
this.setState({
rightTreeCopy,
checkedAllLeftKey,
leftBtnDisabled: !checkedkeys.length
});
// console.log(rightTreeCopy);
};
checkedRight = checkedkeys => {
const { checkedAllLeftKey } = this.state;
let checkAllCopy = cloneDeep(checkedAllLeftKey);
checkedkeys.forEach(item => {
let index = checkAllCopy.findIndex(c => {
return item === c;
});
checkAllCopy.splice(index, 1);
});
//左邊删除右邊選中後的key
this.setState({
checkAllCopy,
rightBtnDisabled: !checkedkeys.length
});
};
//5.把選中的扁平的資料變成樹結構
ListToTree(checkedAllKey) {
//3,防止循環插入重複資料,把children設定null
arr.map(item => {
if (item.children) {
item.children = null;
}
return item;
});
//4.在扁平後的資料中篩選出選中的資料
let selectValue = checkedAllKey.map(item => {
return arr.find(a => {
return item == a.key;
});
});
let copyList = cloneDeep(selectValue);
// console.log(copyList);
copyList.forEach(ele => {
// 第一次forEach周遊到所有的數組對象,不做去重,數組依舊擁有6個元素
let parentId = ele.parentKey;
if (!parentId) {
//是根元素的話 ,不做任何操作.
} else {
//如果ele是子元素的話 ,把ele扔到他的父親的child數組中.它的父元素也可能是别人的子元素
copyList.forEach(d => {
if (d.key === parentId) {
let childArray = d.children;
// 一則避免了去給d.child聲明定義空數組
// childArray為undefined時,用push方法去報undefined.push的錯
if (!childArray) {
childArray = [];
}
// 用push保證同級别的對象有序追加
childArray.push(ele);
d.children = childArray;
} //else的地方不做處理,保證了最深層的對象沒有child屬性
});
}
});
//去除重複元素
copyList = copyList.filter(ele => !ele.parentKey);
return copyList;
}
//把選中的資料設定到右邊
toRight = () => {
const { rightTreeCopy } = this.state;
this.setState({
rightTree: rightTreeCopy,
checkedKeysLeft: {
checked: [],
halfChecked: []
},
leftBtnDisabled: true,
rightBtnDisabled: true
});
};
//取消右邊的資料
toLeft = () => {
const { checkAllCopy, checkedKeysLeft } = this.state;
//console.log(checkAllCopy, checkedKeysLeft);
const rightTreeCopy = this.ListToTree(checkAllCopy);
this.setState({
rightTree: rightTreeCopy,
checkedAllLeftKey: checkAllCopy,
checkedKeysLeft: {
checked: [],
halfChecked: []
},
leftBtnDisabled: true,
rightBtnDisabled: true
});
};
onExpand = expandedKeys => {
this.setState({
expandedKeys,
autoExpandParent: false
});
};
getParentKey = (key, tree) => {
let parentKey;
for (let i = 0; i < tree.length; i++) {
const node = tree[i];
if (node.children) {
if (node.children.some(item => item.key === key)) {
parentKey = node.key;
} else if (this.getParentKey(key, node.children)) {
parentKey = this.getParentKey(key, node.children);
}
}
}
return parentKey;
};
//搜尋
onChange = e => {
const { value } = e.target;
const newarr = cloneDeep(arr);
const newDATA = cloneDeep(DATA);
const expandedKeys = newarr
.map(item => {
if (item.title.indexOf(value) > -1) {
return this.getParentKey(item.key, newDATA);
}
return null;
})
.filter((item, i, self) => item && self.indexOf(item) === i);
this.setState({
expandedKeys,
searchValue: value,
autoExpandParent: true
});
};
loop = data =>
data.map(item => {
//拼接
const index = item.title.indexOf(this.state.searchValue);
const beforeStr = item.title.substr(0, index);
const afterStr = item.title.substr(
index + this.state.searchValue.length
);
const title =
index > -1 ? (
<span>
{beforeStr}
<span style={{ color: 'red' }}>
{this.state.searchValue}
</span>
{afterStr}
</span>
) : (
<span>{item.title}</span>
);
if (item.children) {
return {
title,
key: item.key,
children: this.loop(item.children)
};
}
return {
title,
key: item.key
};
});
render() {
const {
loading,
expandedKeys,
autoExpandParent,
checkedKeysLeft
} = this.state;
return (
<div style={{ display: 'flex' }}>
<div style={{ width: '50%' }}>
<Search
style={{ marginBottom: 8 }}
placeholder="Search"
onChange={this.onChange}
/>
<NuCard loading={loading}>
<Tree
showLine
checkable
checkStrictly={false}
onCheck={this.checked}
onExpand={this.onExpand}
//checkedKeys={checkedKeysLeft}左邊選中的key
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
// onSelect={this.onSelect}
treeData={this.loop(cloneDeep(DATA))}
>
{/* {this.renderTreeNode()} */}
</Tree>
</NuCard>
</div>
<Button
onClick={this.toRight}
disabled={this.state.leftBtnDisabled}
>
toRight
</Button>
<Button
onClick={this.toLeft}
disabled={this.state.rightBtnDisabled}
>
toLeft
</Button>
<div style={{ width: '50%' }}>
<NuCard loading={loading}>
<Tree
showLine
checkable
checkStrictly={false}
onCheck={this.checkedRight}
// onSelect={this.onSelect}
treeData={this.state.rightTree}
>
{/* {this.renderTreeNodeCopy()} */}
</Tree>
</NuCard>
</div>
</div>
);
}
}
export default TransferTree;
const DATA = [
{
title: '一級1',
key: 1,
field: 'name1',
checked: true,
spread: true,
children: [
{
title: '二級1-1 ',
key: 3,
field: 'name11',
children: [
{
title: '三級1-1-3',
key: 23,
field: '',
children: [
{
title: '四級1-1-3-1',
key: 24,
field: '',
children: [
{
title: '五級1-1-3-1-1',
key: 30,
field: ''
},
{
title: '五級1-1-3-1-2',
key: 31,
field: ''
}
]
}
]
},
{
title: '三級1-1-1',
key: 7,
field: '',
children: [
{
title: '四級1-1-1-1 ',
key: 15,
field: ''
}
]
},
{
title: '三級1-1-2',
key: 8,
field: '',
children: [
{
title: '四級1-1-2-1',
key: 32,
field: ''
}
]
}
]
},
{
title: '二級1-2',
key: 4,
spread: true,
children: [
{
title: '三級1-2-1',
key: 9,
field: ''
},
{
title: '三級1-2-2',
key: 10,
field: ''
}
]
},
{
title: '二級1-3',
key: 20,
field: '',
children: [
{
title: '三級1-3-1',
key: 21,
field: ''
},
{
title: '三級1-3-2',
key: 22,
field: ''
}
]
}
]
},
{
title: '一級2',
key: 2,
field: '',
spread: true,
children: [
{
title: '二級2-1',
key: 5,
field: '',
spread: true,
children: [
{
title: '三級2-1-1',
key: 11,
field: ''
},
{
title: '三級2-1-2',
key: 12,
field: ''
}
]
},
{
title: '二級2-2',
key: 6,
field: '',
children: [
{
title: '三級2-2-1',
key: 13,
field: ''
},
{
title: '三級2-2-2',
key: 14,
field: ''
}
]
}
]
},
{
title: '一級3',
key: 16,
field: '',
children: [
{
title: '二級3-1',
key: 17,
field: '',
fixed: true,
children: [
{
title: '三級3-1-1',
key: 18,
field: ''
},
{
title: '三級3-1-2',
key: 19,
field: ''
}
]
},
{
title: '二級3-2',
key: 27,
field: '',
children: [
{
title: '三級3-2-1',
key: 28,
field: ''
},
{
title: '三級3-2-2',
key: 29,
field: ''
}
]
}
]
}
];