Ant Design的可编辑Tree的实现操作


Posted in Javascript onOctober 31, 2020

前言

最近在用Ant Design写一个后台,遇到的需求就是实现一个可动态增减和编辑子节点的Tree。GitHub上看了一圈,没好用和合适的。索性就基于Ant Design中的Tree组件写一个。

实现的效果如下:

可以增加子节点

可以删除子节点

可以编辑子节点信息

可以取消编辑信息

具体的效果图如下:

Ant Design的可编辑Tree的实现操作

主要的就是借助 TreeNode 的 title 属性,它的类型是string|ReactNode。

正文

经过分析,一个节点的数据结构应该是

{
  value: 'Root', // 显示的信息
  defaultValue: 'Root', // 当某一节点进入编辑状态,然后点击close按钮,节点的信息应该恢复原始状态,
  key: '0-1', // 节点的Key,全局唯一
  parentKey: '0', // 父节点的Key
  isEditable: false // 是否处于可编辑状态
  children:[] // 子节点
}

通过数据结构组装TreeNode的代码如下:

data= [
   {
    value: 'Root',
    defaultValue: 'Root',
    key: '0-1',
    parentKey: '0',
    isEditable: false
   }
  ];
  
  state={
    data: this.data
  }
 
renderTreeNodes = data => data.map((item) => {
  if (item.isEditable) { // 编辑状态下
   item.title = (
    <div>
     <input value={item.value}
      onChange={(e) => this.onChange(e, item.key)}/>
     <Icon type='close' style={{marginLeft:10}} onClick={() => this.onClose(item.key, item.defaultValue)}/>
     <Icon type='check' style={{marginLeft:10}} onClick={() => this.onSave(item.key)}/>
    </div>
   );
  } else {
   item.title = (
    <div>
     <span>
      {item.value}
     </span>
     <Icon style={{ marginLeft: 10 }} type='edit' onClick={() => this.onEdit(item.key)} />
     <Icon style={{ marginLeft: 10 }} type='plus' onClick={() => this.onAdd(item.key)} />
     {item.parentKey === '0' ? null : (<Icon style={{ marginLeft: 10 }} type='minus' onClick={() => this.onDelete(item.key)} />)} // 根节点没有删除按钮
    </div>
   )
  }
 
  if (item.children) {
   return (
    <TreeNode title={item.title} key={item.key} dataRef={item}>
     {this.renderTreeNodes(item.children)}
    </TreeNode>
   );
  }
 
  return <TreeNode {...item}/>;
 })
 
 ...
 // 渲染界面
 render() {
  return (
   <div>
    <Tree>
     {this.renderTreeNodes(this.state.data)}
    </Tree>
   </div>
  )
 }

之后所有的增删修改等都是先修改data这个数组中的数据,然后使用this.setState({ data: this.data })更新界面,具体的看下代码就成,很简单。

最后优化这个组件的时候,遇到一个比较坑的。本来想是当在某节点上增加子节点时,父节点自动展开,代码逻辑上没有问题,但是必须手动执行过一次展开或者搜索的操作,所写的逻辑才能生效。

后来没办法,只能在生命周期函数中DOM加载完毕后主动触发下:

componentDidMount() {
  this.onExpand([]); // 手动触发,否则会遇到第一次添加子节点不展开的Bug
 }

代码放在GitHub上了,地址是 react-editable-tree,欢迎有同样需要的小伙伴参考,star和fork 也是极好的。

补充知识:关于antd Select 限制选择个数的解决方案

应用场景描述:

Select 被form 所包裹,且被getFieldDecorator修饰。所以值的改变应该通过form的setFieldsValue方法。

Select模式肯定会是multiple。且以最多三个值举例。

解决思路如下:

1 起初是想在Select的onchange事件中判断values的数量,数量大于三个的时候来重新setFieldsValue;且把最后的选项值替换成刚刚选择的值。

后来发现setFieldsValue方法不起作用,Select的值会一直增加。后来想想可能是 setFieldsValue与onchange 冲突,通过setFieldsValue 无法改变onchange后的值。

2 最后通过重新查看文档。发现还有一个方法可用,即 validator。验证值,通过验证所选值的数量是否大于三个,然后重新setFieldsValue ;发现此法可行。从而解决该疑难杂症。

好,最后附上代码供参考:

changeValues = (rule ,value , callback)=> {
const { setFieldsValue } = this.props.form ;

let newArr ;

if (value.length > 3){


newArr = [].concat(value.slice(0,2), value.slice(-1) ) ;


setFieldsValue({


"languages" : newArr ,


})


callback('最多选择三种语言')

} else {


newArr = value ;


callback()

}
}
 
<FormItem>
{getFieldDecorator('languages', {
rules:[{required: true,message : '请选择三种语言',
validator : changeValues
}],
validateTrigger : 'onChange',
})(
<Select mode='multiple' >
 

<Option key={1} value={1}>1</Option>

<Option key={2} value={2}>2</Option>
 
<Option key={3} value={3}>3</Option>

<Option key={4} value={4}>4</Option>

<Option key={5} value={5}>5</Option>
</Select>
)}
</FormItem>

以上这篇Ant Design的可编辑Tree的实现操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
ExtJS 2.0实用简明教程 之ExtJS版的Hello
Apr 29 Javascript
javaScript(JS)替换节点实现思路介绍
Apr 17 Javascript
jquery 获取 outerHtml 包含当前节点本身的代码
Oct 30 Javascript
分享2个jQuery插件--jquery.fileupload与artdialog
Dec 26 Javascript
JS+CSS实现电子商务网站导航模板效果代码
Sep 10 Javascript
jquery捕捉回车键及获取checkbox值与异步请求的方法
Dec 24 Javascript
node中Express 动态设置端口的方法
Aug 04 Javascript
Bootstrap实现翻页效果
Nov 27 Javascript
百度小程序自定义通用toast组件
Jul 17 Javascript
p5.js实现动态图形临摹
Oct 23 Javascript
vue页面加载时的进度条功能(实例代码)
Jan 13 Javascript
VUE Elemen-ui之穿梭框使用方法详解
Jan 19 Javascript
antd多选下拉框一行展示的实现方式
Oct 31 #Javascript
解决antd 下拉框 input [defaultValue] 的值的问题
Oct 31 #Javascript
Vue使用CDN引用项目组件,减少项目体积的步骤
Oct 30 #Javascript
vue+swiper实现左右滑动的测试题功能
Oct 30 #Javascript
利用vue3+ts实现管理后台(增删改查)
Oct 30 #Javascript
vue项目页面嵌入代码块vue-prism-editor的实现
Oct 30 #Javascript
解决vue侦听器watch,调用this时出现undefined的问题
Oct 30 #Javascript
You might like
session 的生命周期是多长
2006/10/09 PHP
PHP 强制性文件下载功能的函数代码(任意文件格式)
2010/05/26 PHP
php读取图片内容并输出到浏览器的实现代码
2013/08/08 PHP
PHP采用get获取url汉字出现乱码的解决方法
2014/11/13 PHP
PHP常用操作类之通信数据封装类的实现
2017/07/16 PHP
JS 学习笔记 防止发生命名冲突
2009/07/30 Javascript
JavaScript CSS修改学习第五章 给“上传”添加样式
2010/02/19 Javascript
JS自调用匿名函数具体实现
2014/02/11 Javascript
js日期联动示例
2014/05/02 Javascript
JQuery Tips相关(1)----关于$.Ready()
2014/08/14 Javascript
jQuery Ajax和getJSON获取后台普通json数据和层级json数据用法分析
2016/06/08 Javascript
js前端实现图片懒加载(lazyload)的两种方式
2017/04/24 Javascript
D3.js进阶系列之CSV表格文件的读取详解
2017/06/06 Javascript
jquery操作ul的一些操作笔记整理(干货)
2017/08/31 jQuery
webpack分离css单独打包的方法
2018/06/12 Javascript
VuePress 快速踩坑小结
2019/02/14 Javascript
vue实现动态按钮功能
2019/05/13 Javascript
微信小程序 自定义弹窗实现过程(附代码)
2019/12/05 Javascript
[02:10]2018DOTA2亚洲邀请赛赛前采访-Liquid
2018/04/03 DOTA
对Tensorflow中权值和feature map的可视化详解
2018/06/14 Python
Python实现查找最小的k个数示例【两种解法】
2019/01/08 Python
Django之模型层多表操作的实现
2019/01/08 Python
Django框架使用内置方法实现登录功能详解
2019/06/12 Python
Python数据类型之列表和元组的方法实例详解
2019/07/08 Python
python导包的几种方法(自定义包的生成以及导入详解)
2019/07/15 Python
python库matplotlib绘制坐标图
2019/10/18 Python
详解字符串在Python内部是如何省内存的
2020/02/03 Python
英国最大的在线时尚眼镜店:Eyewearbrands
2019/03/12 全球购物
得到Class的三个过程是什么
2012/08/10 面试题
八年级生物教学反思
2014/01/22 职场文书
《孔繁森》教学反思
2014/04/17 职场文书
环保建议书400字
2014/05/14 职场文书
云冈石窟导游词
2015/02/04 职场文书
2015年第31个教师节致辞
2015/07/31 职场文书
合理化建议书范文
2015/09/14 职场文书
SQL基础的查询语句
2021/11/11 MySQL