React树形控件
最近学习了前端的知识,搭建页面过程中,使用树状组件遇到了很大问题,总结一下。(使用的是react3版本,在vscode中进行编写)
1. 首先提供树状组件的数据为树形,树的结构不是这种的,可以利用循环将其修改为次类型。具体结构如下(treeData应该放在this.state中)
treeData = [
{
title: '0-0',
key: '0-0',
children: [
{
title: '0-0-0',
key: '0-0-0',
children: [
{ title: '0-0-0-0', key: '0-0-0-0' },
{ title: '0-0-0-1', key: '0-0-0-1' },
{ title: '0-0-0-2', key: '0-0-0-2' },
],
},
{
title: '0-0-1',
key: '0-0-1',
children: [
{ title: '0-0-1-0', key: '0-0-1-0' },
{ title: '0-0-1-1', key: '0-0-1-1' },
{ title: '0-0-1-2', key: '0-0-1-2' },
],
},
{
title: '0-0-2',
key: '0-0-2',
},
],
},
{
title: '0-1',
key: '0-1',
children: [
{ title: '0-1-0-0', key: '0-1-0-0' },
{ title: '0-1-0-1', key: '0-1-0-1' },
{ title: '0-1-0-2', key: '0-1-0-2' },
],
},
{
title: '0-2',
key: '0-2',
},
];
2. 根据ant design 中的树状结构选择可用的树。以可多选的树形结构为例子:
<Tree
checkable //是否可以在节点前添加 Checkbox 复选框,未使用可以不写
onExpand={this.onExpand.bind(this)}//展开/收起节点时触发,一般情况下不需要对onExpand函数进行修改
expandedKeys={this.state.expandedKeys} //(受控)展开指定的树节点, expandedKeys必须是一个array类型的数据
autoExpandParent={this.state.autoExpandParent}//是否自动展开父节点
onCheck={this.onCheck.bind(this)} //点击复选框触发,一般情况下不需要对onCheck函数进行修改
checkedKeys={this.state.checkedKeys}//(受控)选中复选框的树节点(注意:父子节点有关联,如果传入父节点 key,则子节点自动选中;相应当子节点 key 都传入,父节点也自动选中。当设置checkable和checkStrictly,它是一个有checked和halfChecked属性的对象,并且父子节点的选中与否不再关联. checkedKeys也需要是array类型的数据
onSelect={this.onSelect.bind(this)} //点击树节点触发,使用时想要点击父节点时展开树,并且不进行页面刷新,因此需要对onSelect函数进行修改。
//紧接着上方的onSelect={this.onSelect.bind(this)}
selectedKeys={this.state.selectedKeys}//(受控)设置选中的树节点, selectedKeys需要是array类型的数据
>
{this.renderTreeNodes(treeData)} //树的结点采用一层一层循环嵌套的方式进行的,先进行父节点的调用,如果此父节点有chidren属性,则再次调用renderTreeNodes方法,依次循环。
</Tree>
//以下代码需要放在render外面
//函数开始
onSelect(selectedKeys, info) {
let { expandedKeys } = this.state;
// console.log("onSelect", selectedKeys, info);
let nameList = selectedKeys.length > 0 ? selectedKeys[0].split('-') : []
if (nameList.length == 2) { //通过判断节点是父节点还是子节点判断是否调用onExpend函数,是父节点就将点击的父节点放到expandedKeys 列表中,并调用onExpend,否则根据点击子节点的信息调用url 页面。
if (expandedKeys.indexOf(selectedKeys[0]) == -1) {
expandedKeys.push(selectedKeys[0])
this.setState({ expandedKeys: expandedKeys }, () => {
this.onExpand(this.state.expandedKeys)
})
return;
}
let keylist = []
for (let i of expandedKeys) {
if (i == selectedKeys[0]) {
}
else {
keylist.push(i)
}
}
// console.log(keylist)
this.setState({ expandedKeys: keylist })
this.onExpand(keylist)
}
else {
if (nameList.length == 3) {
//此处根据个人情况进行编写进行的操作就可以了
}
}
};
//函数结束
onSelect函数 需要对selectedKeys进行判断(我设置的父节点key是“0-0”,子节点key是“0-0-0”),可以根当前的key进行父子节点的判断,如果是父节点,就给expandedKeys重新赋值后调用onExpand函数对点击的节点进行展开,如果是子节点,就根据获取info.selectedNodes[0].props中的内容进行更新this.state中的内容。
//renderTreeNodes方法如下:
//函数开始
renderTreeNodes(data) {
let treedatas = data.map(item => {
if (item.children) {
return (
<TreeNode title={item.title} key={item.key} dataRef={item}>
{this.renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode key={item.key} {...item} />;
});
return treedatas
}
//函数结束
//onExpand函数和onCheck函数不需要进行改动
onExpand(expandedKeys) {
console.log('onExpand', expandedKeys);
// if not set autoExpandParent to false, if children expanded, parent can not collapse.
// or, you can remove all expanded children keys.
this.setState({
expandedKeys,
autoExpandParent: false,
});
};
onCheck (checkedKeys){
console.log('onCheck', checkedKeys);
this.setState({ checkedKeys });
};
经过这些修改,基本上可以完成树形组件,注意,我设计的树形组件父类节点是可以多选,也就是可以同时展开多个父类节点,但是子类节点只能选择一个,如果想要可以选择多个子节点,可以查看antd design官网进行查看。
3. 一些初始化问题
在this.state中需要进行一些初始化操作,具体如下:
注意,expandedKeys,checkedKeys和selectedKeys在官网上明确要求是array类型,我试过改成字符串,会出现一些bug,不推荐对其类型进行修改。
this.state = {
expandedKeys: ['0-0-0', '0-0-1'],//根据自己的实际情况选择默认展开的父节点
autoExpandParent: true,
checkedKeys: ['0-0-0'],
selectedKeys: [],
};
4. 效果图
最后放下我的效果图(类似的哈,大概结构都是一样的)
参考:
https://ant.design/index-cn