React实现点击删除列表中对应项


Posted in Javascript onJanuary 10, 2017

点击删除按钮,删除列表中对应项本来是React比较基础的应用,可是应用情况变得复杂了以后,我还真想了一会儿才搞定。

简化一下应用场景:点击新增按钮,增加一条输入框,点击输入框旁边的按钮,删除该输入框(不能删错了啊)。

先说第一种方法

问题刚上手,首先规划级别:一个输入框和对应删除按钮为一个子组件,整体为父组件即可方便处理。

注意的点:生成的一坨输入框是一个数组,为了准确删掉对应项,生成时要编号。点击删除按钮要反馈对应编号,然后进行删除。

现在的逻辑是:整个待展示列表(由子组件组成的数组)是个state,添加按钮会增加一个元素到这个state里面,添加的方法如下:

add(){
  var lists=this.state.lists;
  lists.push(<List key={this.state.lists.length} index={this.state.lists.length} delete={this.delete}/>);
  this.setState({lists:lists})
 }

注意一点,这个index属性是固定的,子组建生成后就固定了,这就为你未来挖了一个坑。

删除按钮当然就是从这个state列表里删除对应元素了,问题一来了,我怎么知道是第几个元素?一拍脑袋这还不简单,event.target 获取点击的标签,在标签上写个index属性告诉delete方法是第几个元素不就得了?试了发现不行,看看文档,event.target确实获取dom元素没毛病,但是index这个属性原生dom根本不承认啊,怎么办?data-index就行了,前面加 data- 就是dom承认的自定义属性了。

写完了又想起了两个方法,一个是在删除按钮绑定删除事件的时候,.bind(this,index),index是你准备删掉的是第几个或者表示出来你要删哪个就行。另一个是搞个闭包,就能把index参数传进去了(事件绑定一个立即执行的方程传入参数,该方程返回目标方程)。

第一个问题解决,删除的方法如下:

delete(e){
  var index=e.target.getAttribute("data-index");
  var lists=this.state.lists;
  lists.splice(index,1);
  this.setState({lists:lists})
 }

data-index告诉你要删除第几个元素,然后把它从state里踢出去就行了。这回掉进了一个真正意义上的坑:有时候删的不是对应的元素!乱套了!

好吧,我沉思了5分钟,想到了为什么:生成列表的时候index已经固定,但删除列表的时候我们只告诉他删除的是第index项!问题严重了,举个例子,有两项,index 0和1 你点0,好吧第0项删掉了,你再点1,疑?没反应了,因为你打算删除第1项,而列表中目前只有第0项(就是原来的第一项,原来的第0项删除后他就成了第0项)!这会导致各种乱套,考虑到生成列表的index是列表长度表示的就更乱了。

解决方式:delete方法里修改一行:

lists.splice(index,1,"");

好了,删除的元素我用空字符串代替,这样顺序和删除的项,还有以后添加的项的index都不会乱了,给自己点赞。到这里第一种方法实现了目标。

Code pen 地址:http://codepen.io/huanqingli/pen/dNyQez

完整代码:

class List extends React.Component {
 render() {
  return (<div><input type="text" defaultValue={this.props.index}/>
   <span onClick={this.props.delete} data-index={this.props.index}>X</span></div>)
 }
}
class Lists extends React.Component {
 constructor(props) {
  super(props);
  this.add=this.add.bind(this);
  this.delete=this.delete.bind(this);
  this.state={
   lists:[]
  }
 }
 add(){
  var lists=this.state.lists;
  lists.push(<List key={this.state.lists.length} index={this.state.lists.length} delete={this.delete}/>);
  this.setState({lists:lists})
 }
 delete(e){
  var index=e.target.getAttribute("data-index");
  var lists=this.state.lists;
  console.log(index)
  lists.splice(index,1);
  this.setState({lists:lists})
 }
 render() {
  return (<div>
   <span onClick={this.add}>添加</span>
   {this.state.lists}
   </div>)
 }
}
ReactDOM.render(
 <Lists/>,
 document.getElementById('lists')
);

这种方法有利有弊,所以我找到了第二种方法,具体情况择优使用。

第二种方法。总体来讲推荐这种方法。

在state里保存要展示的数据,在render里动态生成子组件组,然后添加删除都是操作保存数据的state,render里的子组件会自动刷新。这种方式应该是更贴近React思路的,用数据展现界面。如果你要展现一组数据,这种方法很自然,但如果展现的是一个动态的表单,稍微麻烦一点,但也可以做,而且我依然推荐用这种方式。

这种方法做个todolist就很简单,这里依然做上文的例子,稍微麻烦一点,也会理解的更深入一点。

整体结构和第一种方法一样,只不过这次state里面不是子组件,先用空字符串组成的数组代替,仅仅是为了render的时候知道有几个子组件而已。添加的时候也要push空字符串,等输入框输入数据后,更新state中的内容,做到数据和界面同步。

render子组件的部分:

{this.state.lists.map(function (item,index) {
    return <List key={index} index={index} delete={this.delete}/>
   }.bind(this))}

添加的方法变成:

add(){
  var lists=this.state.lists;
  lists.push("");
  this.setState({lists:lists})
 }

这就能跑了,这有个小坑,稍有不慎你发现你怎么删都是删列表的最后一项,其实数据操作没问题,关键是这个存在感比较低的key,必须特定项有给定的key你用动态的index他就懵了,不知道删哪个了,他就吧最后一个删了。废话不多说(该程序因为key键取值的问题有一个小问题):

Code pen 地址:http://codepen.io/huanqingli/pen/xgxNYN

整体代码:

class List extends React.Component {
 constructor(props){
  super(props);
  this.upData=this.upData.bind(this);
 }
 upData(e){
  this.props.upData(this.props.index,e.target.value)
 }
 render() {
  return (<div><input type="text" onBlur={this.upData} defaultValue={this.props.item?this.props.item:""}/>
   <span onClick={this.props.delete} data-index={this.props.index}>X</span></div>)
 }
}
class Lists extends React.Component {
 constructor(props) {
  super(props);
  this.add=this.add.bind(this);
  this.delete=this.delete.bind(this);
  this.upData=this.upData.bind(this);
  this.state={
   lists:[]
  }
 }
 add(){
  var lists=this.state.lists;
  lists.push("");
  this.setState({lists:lists})
 }
 delete(e){
  var index=e.target.getAttribute("data-index");
  var lists=this.state.lists;
  lists.splice(index,1);
  this.setState({lists:lists})
 }
 upData(i,x){
  var lists=this.state.lists;
  lists[i]=x;
  console.log(lists);
  this.setState({lists:lists});
 }
 render() {
  return (<div>
   <span onClick={this.add}>添加</span>
   {this.state.lists.map(function (item,index) {
    return <List key={item?item:index} index={index} delete={this.delete} upData={this.upData} item={item}/>
   }.bind(this))}
   </div>)
 }
}
ReactDOM.render(
 <Lists />, document.getElementById('lists')
)

这种方法经常也会有点小坑,也比较好解决。

总结:两种方法各有利弊,推荐第二种,符合REACT设计思路,但第一种有时候解决问题很方便。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
JavaScript 密码强度判断代码
Sep 05 Javascript
jquery1.4 教程二 ajax方法的改进
Feb 25 Javascript
基于JavaScript制作霓虹灯文字 代码 特效
Sep 01 Javascript
微信小程序  TLS 版本必须大于等于1.2问题解决
Feb 22 Javascript
JavaScript实现移动端页面按手机屏幕分辨率自动缩放的最强代码
Aug 18 Javascript
基于Bootstrap表单验证功能
Nov 17 Javascript
JavaScript累加、迭代、穷举、递归等常用算法实例小结
May 08 Javascript
WebPack配置vue多页面的技巧
May 15 Javascript
详解如何解决vue开发请求数据跨域的问题(基于浏览器的配置解决)
Nov 12 Javascript
浅析vue插槽和作用域插槽的理解
Apr 22 Javascript
vue+render+jsx实现可编辑动态多级表头table的实例代码
Apr 01 Javascript
基于ant design日期控件使用_仅月份的操作
Oct 27 Javascript
微信小程序 radio单选框组件详解及实例代码
Jan 10 #Javascript
微信小程序 slider 详解及实例代码
Jan 10 #Javascript
微信小程序 switch组件详解及简单实例
Jan 10 #Javascript
微信小程序 textarea 组件详解及简单实例
Jan 10 #Javascript
微信小程序 picker-view 组件详解及简单实例
Jan 10 #Javascript
微信小程序 picker 组件详解及简单实例
Jan 10 #Javascript
微信小程序 label 组件详解及简单实例
Jan 10 #Javascript
You might like
什么是调频(FM)、调幅(AM)、短波(SW)、长波(LW)
2021/03/01 无线电
php中比较简单的导入phpmyadmin生成的sql文件的方法
2011/06/28 PHP
ThinkPHP结合ajax、Mysql实现的客户端通信功能代码示例
2014/06/23 PHP
PHP生成压缩文件实例
2015/02/07 PHP
解决php表单重复提交实现方法
2015/09/29 PHP
JavaScript面向对象之静态与非静态类
2010/02/03 Javascript
setTimeout函数兼容各主流浏览器运行执行效果实例
2013/06/13 Javascript
js中方法重载如何实现?以及函数的参数问题
2013/08/01 Javascript
javascript仿php的print_r函数输出json数据
2013/09/13 Javascript
jQuery实现字符串按指定长度加入特定内容的方法
2015/03/11 Javascript
使用json来定义函数,在里面可以定义多个函数的实现方法
2016/10/28 Javascript
实现一个简单的vue无限加载指令方法
2017/01/10 Javascript
jQuery Jsonp跨域模拟搜索引擎
2017/06/17 jQuery
深入理解Vue.js轻量高效的前端组件化方案
2018/12/10 Javascript
Net微信网页开发 使用微信JS-SDK获取当前地理位置过程详解
2019/08/26 Javascript
解决layui调用自定义方法提示未定义的问题
2019/09/14 Javascript
vue实例的选项总结
2020/06/09 Javascript
微信小程序之导航滑块视图容器功能的实现代码(简单两步)
2020/06/19 Javascript
vue3.0自定义指令(drectives)知识点总结
2020/12/27 Vue.js
[03:18]DOTA2亚洲邀请赛小组赛第一日 RECAP赛事回顾
2015/01/30 DOTA
Python生成不重复随机值的方法
2015/05/11 Python
在Django框架中编写Context处理器的方法
2015/07/20 Python
Python实现针对中文排序的方法
2017/05/09 Python
python 文件操作删除某行的实例
2017/09/04 Python
python数据挖掘需要学的内容
2019/06/23 Python
python实现逆滤波与维纳滤波示例
2020/02/26 Python
GDAL 矢量属性数据修改方式(python)
2020/03/10 Python
如何利用python生成MD5并去重
2020/12/07 Python
Python3自带工具2to3.py 转换 Python2.x 代码到Python3的操作
2021/03/03 Python
信息技术专业个人自我评价
2013/12/11 职场文书
幼儿教师师德师风演讲稿
2014/08/22 职场文书
招商引资工作汇报
2014/10/28 职场文书
检讨书模板大全
2015/05/07 职场文书
国庆放假通知怎么写
2015/07/30 职场文书
毕业欢送晚会主持词
2019/06/25 职场文书
Win11如何修改dns?Win11修改dns图文教程
2022/01/18 数码科技