纵有疾风起
人生不言弃

antd———Tree结构之探索遍历及删除

前言:笔者在前端开发过程中遇到关于树的问题,把antd官方的Tree组件直接拿下来用了,刚开始其他方法都还好,当需求中写个节点的删除功能的时候,因为算法功底不好,导致此功能实现不了,所以有了此文

背景

前端项目是react+umi+antd,这个用过的都知道好,不做赘述,笔者先找到了这个antd官方提供的Tree组件

export default class MyTree extends React.Component {  state = {    treeData: [      {        key:'1',        title:"第一部分",        children:[          {key:'1-1',title:"一、二级标题",},          {key:'1-2',title:"二、二级标题",},          {key:'1-3',title:"三、二级标题",},          {key:'1-4',title:"四、二级标题",}        ]      },      {        key:'2',        title:"第二部分",        children:[          {            key:'2-1',            title:"一、二级标题",            children:[              {key:'2-1-1',title:"(一)三级标题",},              {key:'2-1-2',title:"(二)三级标题",},              {key:'2-1-3',title:"(三)三级标题",},            ]          },          {            key:'2-2',            title:"二、二级标题",            children:[              {key:'2-2-1',title:"(一)三级标题",},              {key:'2-2-2',title:"(二)三级标题",}            ]          },          {            key:'2-3',            title:"三、二级标题",            children:[              {key:'2-3-1',title:"(一)三级标题",},              {key:'2-3-2',title:"(二)三级标题",},            ]          },          {            key:'2-4',            title:"四、二级标题",            children:[              {key:'2-4-1',title:"(一)三级标题",},              {key:'2-4-2',title:"(二)三级标题",},            ]          },          {            key:'2-5',            title:"五、二级标题",            children:[              {key:'2-5-1',title:"(一)三级标题",},              {key:'2-5-2',title:"(二)三级标题",},            ]          },        ]      },      {        key:'3',        title:"第三部分",        children:[          {            key:'3-1',            title:"一、二级标题",            children:[              {key:'3-1-1',title:"(一)综合医院",},              {key:'3-1-2',title:"(二)重点专科医院",},            ]          },          {            key:'3-2',            title:"二、二级标题",            children:[              {key:'3-2-1',title:"(一)三级标题",},              {key:'3-2-2',title:"(二)三级标题",},            ]          },          {            key:'3-3',            title:"三、二级标题",            children:[              {key:'3-3-1',title:"(一)三级标题",},              {key:'3-3-2',title:"(二)三级标题",},            ]          },          {            key:'3-4',            title:"四、二级标题",            children:[              {key:'3-4-1',title:"(一)三级标题",},              {key:'3-4-2',title:"(二)三级标题",},            ]          },        ]      }    ]  }   renderTreeNodes = data => data.map((item) => {    if (item.children) {      return (        <TreeNode title={item.title} key={item.key} dataRef={item}>          {this.renderTreeNodes(item.children)}        </TreeNode>      );    }    return <TreeNode {...item} dataRef={item} />;  })  render() {    return (      <Tree>        {this.renderTreeNodes(this.state.treeData)}      </Tree>    );  }}

通过这个结构,render出来的结果,和https://ant.design/components/tree-cn/中的效果

antd———Tree结构之探索遍历及删除插图
tree-demo-v1

寻找删除之道

这个时候又行业大佬提供了以下思路

1:递归去找到然后删除
2:把key值不等于这个得,重新放入一个新数组,最后重新设置state
3:把key值直接设置为className,找dom数然后删除

其实三种方法都可以进行探索,网上找了N多资料,都不得解,最终晚上灵光一闪,得出以下思路:
如果把data数组,都放在最顶层,取消children数组,然后给每个都加上一个parentId,
1:这样满足了render的时候可以进行递归,
2:要删除的时候,或者更改的时候,遍历data,就能找打key,进行删除,当然,如果删除的是父级,同时也可以删除所有子级节点
以下是代码

export default class MyTree extends React.Component {  state = {    data:[      {key:'1',title:'第一部分',parentId:'-1'},      {key:'1-1',title:'一、二级标题',parentId:'1'},      {key:'1-2',title:'二、二级标题',parentId:'1'},      {key:'1-3',title:'三、二级标题',parentId:'1'},      {key:'1-4',title:'四、二级标题',parentId:'1'},      {key:'2',title:'第二部分',parentId:'-1'},      {key:'2-1',title:'一、二级标题',parentId:'2'},      {key:'2-1-1',title:'(一)三级标题',parentId:'2-1'},      {key:'2-1-2',title:'(二)三级标题',parentId:'2-1'},      {key:'2-1-3',title:'(三)三级标题',parentId:'2-1'},      {key:'2-2',title:'二、二级标题',parentId:'2'},      {key:'2-2-1',title:'(一)三级标题',parentId:'2-2'},      {key:'2-2-2',title:'(二)三级标题',parentId:'2-2'},      {key:'2-3',title:'三、二级标题',parentId:'2'},      {key:'2-3-1',title:'(一)三级标题',parentId:'2-3'},      {key:'2-3-2',title:'(二)三级标题',parentId:'2-3'},      {key:'2-4',title:'四、二级标题',parentId:'2'},      {key:'2-4-1',title:'(一)三级标题',parentId:'2-4'},      {key:'2-4-2',title:'(二)三级标题',parentId:'2-4'},      {key:'2-5',title:'五、二级标题',parentId:'2'},      {key:'2-5-1',title:'(一)三级标题',parentId:'2-5'},      {key:'2-5-2',title:'(二)三级标题',parentId:'2-5'},      {key:'3',title:'第三部分',parentId:'-1'},      {key:'3-1',title:'一、二级标题',parentId:'3'},      {key:'3-1-1',title:'(一)三级标题',parentId:'3-1'},      {key:'3-1-2',title:'(二)三级标题',parentId:'3-1'},      {key:'3-2',title:'二、二级标题',parentId:'3'},      {key:'3-2-1',title:'(一)三级标题',parentId:'3-2'},      {key:'3-2-2',title:'(二)三级标题',parentId:'3-2'},      {key:'3-3',title:'三、二级标题',parentId:'3'},      {key:'3-3-1',title:'(一)三级标题',parentId:'3-3'},      {key:'3-3-2',title:'(二)三级标题',parentId:'3-3'},      {key:'3-4',title:'四、二级标题',parentId:'3'},      {key:'3-4-1',title:'(一)三级标题',parentId:'3-4'},      {key:'3-4-2',title:'(二)三级标题',parentId:'3-4'},    ],  }  // 根据父级找到所有子级节点  getByParentId(parentId){    return this.state.data.filter(item => {      return item.parentId === parentId;    })  }  renderTreeNode = (parentId) => {    // 先找到子级节点    var tmp = this.getByParentId(parentId);    if(tmp.length > 0){      // 遍历铺页面,如果数组长度不为0则证明子级不为空      return tmp.map(item =>{        return (          <TreeNode title={item.title} key={item.key} dataRef={item}>            {this.renderTreeNode(item.key)}          </TreeNode>        );      })    }  }  render() {    return (      <Tree>        {/*先找到所有parentId为-1的顶级节点*/}        {this.renderTreeNode("-1")}      </Tree>    );  }}
antd———Tree结构之探索遍历及删除插图1
tree-demo-v2

接下来就好办了,删除方法和右键响应方法

  //简单处理,右键删除  handleRightClick = (e) =>{    let key = e.node.props.dataRef.key;    this.handleDelete(key)  }    //根据key删除节点  handleDelete = (key) => {    let {data} = this.state;    data.splice(data.findIndex(item => item.key === key),1)    this.setState(data);  }

Tree绑定右键处理事件

<Tree onRightClick={this.handleRightClick}>          {/*先找到所有parentId为-1的顶级节点*/}          {this.renderTreeNode("-1")}    </Tree>

效果:

antd———Tree结构之探索遍历及删除插图2
image.png

同理,要对节点进行其他遍历操作就更方便,不会像第一次那样做各种递归处理,给不同节点增加不同样式,修改内容等等,方便很多

鉴于楼下有个小伙伴,提问如何更换位置,今日有空,也实现出来,大家多多指导

class MyTree extends React.Component {  state = {    currentNode: null,    data:[      {key:'1',title:'第一部分',parentId:'-1'},      {key:'2',title:'第二部分',parentId:'-1'},      {key:'3',title:'第三部分',parentId:'-1'},      {key:'1-1',title:'一、二级标题',parentId:'1'},      {key:'1-2',title:'二、二级标题',parentId:'1'},      {key:'1-3',title:'三、二级标题',parentId:'1'},      {key:'1-4',title:'四、二级标题',parentId:'1'},      {key:'2-1',title:'一、二级标题',parentId:'2'},      {key:'2-2',title:'二、二级标题',parentId:'2'},      {key:'2-3',title:'三、二级标题',parentId:'2'},      {key:'2-4',title:'四、二级标题',parentId:'2'},      {key:'2-5',title:'五、二级标题',parentId:'2'},      {key:'3-1',title:'一、二级标题',parentId:'3'},      {key:'3-2',title:'二、二级标题',parentId:'3'},      {key:'3-3',title:'三、二级标题',parentId:'3'},      {key:'3-4',title:'四、二级标题',parentId:'3'},      {key:'2-1-1',title:'(一)三级标题',parentId:'2-1'},      {key:'2-1-2',title:'(二)三级标题',parentId:'2-1'},      {key:'2-1-3',title:'(三)三级标题',parentId:'2-1'},      {key:'2-2-1',title:'(一)三级标题',parentId:'2-2'},      {key:'2-2-2',title:'(二)三级标题',parentId:'2-2'},      {key:'2-3-1',title:'(一)三级标题',parentId:'2-3'},      {key:'2-3-2',title:'(二)三级标题',parentId:'2-3'},      {key:'2-4-1',title:'(一)三级标题',parentId:'2-4'},      {key:'2-4-2',title:'(二)三级标题',parentId:'2-4'},      {key:'2-5-1',title:'(一)三级标题',parentId:'2-5'},      {key:'2-5-2',title:'(二)三级标题',parentId:'2-5'},      {key:'3-1-1',title:'(一)三级标题',parentId:'3-1'},      {key:'3-1-2',title:'(二)三级标题',parentId:'3-1'},      {key:'3-2-1',title:'(一)三级标题',parentId:'3-2'},      {key:'3-2-2',title:'(二)三级标题',parentId:'3-2'},      {key:'3-3-1',title:'(一)三级标题',parentId:'3-3'},      {key:'3-3-2',title:'(二)三级标题',parentId:'3-3'},      {key:'3-4-1',title:'(一)三级标题',parentId:'3-4'},      {key:'3-4-2',title:'(二)三级标题',parentId:'3-4'},    ],  }  // 根据父级找到所有子级节点  getByParentId(parentId){    return this.state.data.filter(item => {      return item.parentId === parentId;    })  }  renderTreeNode = (parentId) => {    // 先找到子级节点    let tmp = this.getByParentId(parentId);    if(tmp.length > 0){      // 遍历铺页面,如果数组长度不为0则证明子级不为空      return tmp.map(item =>{        return (          <TreeNode title={item.title} key={item.key} dataRef={item}>            {this.renderTreeNode(item.key)}          </TreeNode>        );      })    }  }  handleRightClick = ({event,node}) =>{    let key = node.props.dataRef.key;    this.handleDelete(key)  }  /**    * 上下移动    */  handleMoveOn=()=> {    let data = this.state.data;    for(let i = 0; i< data.length; i++){      if(data[i].key == this.state.currentNode && i >= 1){          let tmp = data[i];          data[i] = data[i-1]          data[i-1] = tmp;      }    }    this.setState(data)  }  handleClick=(e)=>{    console.log(1)    this.setState({currentNode:e})  }  //根据key删除节点  handleDelete = (key) => {    let {data} = this.state;    data.splice(data.findIndex(item => item.key === key),1)    this.setState(data);  }  render() {    return (      <div>        <div className={styles.btn}>          <Button onClick={this.handleMoveOn} disabled={this.state.currentNode==null}>上移</Button>        </div>        <Tree onRightClick={this.handleRightClick} className={styles.normal} onSelect={this.handleClick}>          {/*先找到所有parentId为-1的顶级节点*/}          {this.renderTreeNode("-1")}        </Tree>      </div>    );  }}
antd———Tree结构之探索遍历及删除插图3
result

鸣谢:感谢antd、umi 提供优秀的前端框架
版权声明:本文原创,转载请声明出处,谢谢

文章转载于:https://www.jianshu.com/p/70660590db2d

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » antd———Tree结构之探索遍历及删除
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录