ReactJs之循环时的key属性
2018-01-04 10:46
330 查看
总结下遇到的问题点,在我们做一些循环生成组件的时候会发现,如果没有key属性经常报警告,看一下实例
在一些组件性能优化方面看到了这个的一些讲解
首先学习的网站
官方文档 https://reactjs.org/docs/lists-and-keys.html
官方文档:动态组件key的作用
民间文档:进一步阐述和论证
loverajoel/jstips:Github上一个每天分享js相关经验的项目
核心内容: React是根据组件上设定的key属性来生成该组件唯一的标识,只有key改变了,React才会更新组件,否则重用该组件。如果想要更新组件内容,请保证每次的key都不一样。
建议大家先看第二个文档:民间文档:进一步阐述和论证,该文档有例子演示也有相应的解决方法。解决方法的核心还是这句话:如果想要更新组件内容,请保证当前组件的key与上一状态组件的key不同。
React修炼之路(一)里面实现组件更新的方法就不说了,这里说说上面文档给我的启发。首先要明确自己的业务需求。
你的组件不是动态组件(不需要动态更新),例如你一个列表只做展示,第一次render出来后就不会改变里面的内容,那么你不需要指定key(不指定key时,React也会生成一个默认的标识),或者将index作为key,只要key不重复即可。
你的组件是动态组件(需要动态更新),例如你一个列表做展示时,能向列表添加或删除元素,此时组件是需要刷新的,刷新的依据就是key,对于相同的key,React会采取和上一次刷新同样的方式。这个时候,如果你采取index作为key,那么假设你在列表顶部添加了元素,那么新的元素的key就是index=0,和上一次刷新时旧顶部元素的key相同,此时React将认为这是这个新元素就是就顶部元素,所以就按照顶部元素的内容刷新该元素,导致新元素的内容就是以前的内容,这个和我的预期不一致,我们预期是顶部元素显示新的内容。亲自试一试。
我希望自己讲得足够清楚,要是不够清楚的话,千万要试一试,不过大概实际开发都是遇到问题再去深入学习的吧,实践越多,遇到的问题越多,就能学到越多。
那么现在我们都知道了,想要组件动态刷新,只要每次刷新都赋予一个新的独一无二的key即可,具体做法有很多种,民间文档:进一步阐述和论证,上面提到的文档后面就给出了几种方法,我没试过,大家感兴趣可以去试试。
我的方法,之前查阅资料想了解随机数的生产原理时,看到这么一句话:
逝者如斯夫,时间就是一个随机数。
很有哲理味道的一句话,所以我就采取了时间作为key,那么每次生成的key都是当前时间,是独一无二的,能确保React的动态刷新。代码如下:
上一篇博客的代码
2
3
4
5
6
7
8
9
10
11
12
13
14
新的代码,区别在于将 li 标签的key由index换成当前时间
2
3
4
5
6
7
8
9
10
11
12
13
14
乍一看是没问题的,完美解决问题,但是一运行,结果,你猜。不卖关子了,直接上代码,正确做法是这样的。
1月14日更新,+new Date() 等同于 new Date().getTime()
哈哈,new Date().getTime()返回了一个精确到毫秒的时间,也就是说,如果是毫秒内的,这个返回值是一样的,也就是key一样,这是React不允许的,直接报错。而恰好你的服务器就是那么快,每个li的生成耗时是毫秒内的,此处的解决方法就是在该基础上index,这样生成的key才是独一无二的。
虽然以前写了下面这个函数能实现动态更新,但是有两个弊端:
2
3
4
5
6
7
一,倒不是代码量的问题,即使以后this.setState说不定会持续增多,但最主要的还是代码维护的问题,若采用了以前的方法,每次state的增减都要去维护componentWillReceiveProps这个方法。
二,以前的方法每次都会更新所有的组件,而有时候你不需要更新所有的组件。例如,在增加一项的时候,你并不需要更新其余项,此时你只需要给新的一样设置新的独一无二的key,而其余项key不变即能实现你的业务逻辑。举个例子吧。
2
3
4
5
6
7
8
9
10
11
核心内容:
可见,只有id,order,color有改变的时候key才会改变,这大概就是key的意义所在吧。
在一些组件性能优化方面看到了这个的一些讲解
首先学习的网站
官方文档 https://reactjs.org/docs/lists-and-keys.html
官方文档:动态组件key的作用
民间文档:进一步阐述和论证
loverajoel/jstips:Github上一个每天分享js相关经验的项目
核心内容: React是根据组件上设定的key属性来生成该组件唯一的标识,只有key改变了,React才会更新组件,否则重用该组件。如果想要更新组件内容,请保证每次的key都不一样。
建议大家先看第二个文档:民间文档:进一步阐述和论证,该文档有例子演示也有相应的解决方法。解决方法的核心还是这句话:如果想要更新组件内容,请保证当前组件的key与上一状态组件的key不同。
三,代码示例
React修炼之路(一)里面实现组件更新的方法就不说了,这里说说上面文档给我的启发。首先要明确自己的业务需求。你的组件不是动态组件(不需要动态更新),例如你一个列表只做展示,第一次render出来后就不会改变里面的内容,那么你不需要指定key(不指定key时,React也会生成一个默认的标识),或者将index作为key,只要key不重复即可。
你的组件是动态组件(需要动态更新),例如你一个列表做展示时,能向列表添加或删除元素,此时组件是需要刷新的,刷新的依据就是key,对于相同的key,React会采取和上一次刷新同样的方式。这个时候,如果你采取index作为key,那么假设你在列表顶部添加了元素,那么新的元素的key就是index=0,和上一次刷新时旧顶部元素的key相同,此时React将认为这是这个新元素就是就顶部元素,所以就按照顶部元素的内容刷新该元素,导致新元素的内容就是以前的内容,这个和我的预期不一致,我们预期是顶部元素显示新的内容。亲自试一试。
我希望自己讲得足够清楚,要是不够清楚的话,千万要试一试,不过大概实际开发都是遇到问题再去深入学习的吧,实践越多,遇到的问题越多,就能学到越多。
那么现在我们都知道了,想要组件动态刷新,只要每次刷新都赋予一个新的独一无二的key即可,具体做法有很多种,民间文档:进一步阐述和论证,上面提到的文档后面就给出了几种方法,我没试过,大家感兴趣可以去试试。
我的方法,之前查阅资料想了解随机数的生产原理时,看到这么一句话:
逝者如斯夫,时间就是一个随机数。
很有哲理味道的一句话,所以我就采取了时间作为key,那么每次生成的key都是当前时间,是独一无二的,能确保React的动态刷新。代码如下:
上一篇博客的代码
render: function(){ var that = this; return( <ul> { this.state.programs.map(function(program,index) { return <li key={index} className="channel-program"> <ChannelProgram program_index={index} day={that.props.day} change={that.props.change} bill={program}/> </li>; }) } </ul> ); }1
2
3
4
5
6
7
8
9
10
11
12
13
14
新的代码,区别在于将 li 标签的key由index换成当前时间
render: function(){ var that = this; return( <ul> { this.state.programs.map(function(program,index) { return <li key={new Date().getTime()} className="channel-program"> <ChannelProgram program_index={index} day={that.props.day} change={that.props.change} bill={program}/> </li>; }) } </ul> ); }1
2
3
4
5
6
7
8
9
10
11
12
13
14
乍一看是没问题的,完美解决问题,但是一运行,结果,你猜。不卖关子了,直接上代码,正确做法是这样的。
key={new Date().getTime() + index}1
1月14日更新,+new Date() 等同于 new Date().getTime()
key={+new Date() + index}1
哈哈,new Date().getTime()返回了一个精确到毫秒的时间,也就是说,如果是毫秒内的,这个返回值是一样的,也就是key一样,这是React不允许的,直接报错。而恰好你的服务器就是那么快,每个li的生成耗时是毫秒内的,此处的解决方法就是在该基础上index,这样生成的key才是独一无二的。
对比之前方法的优势所在
虽然以前写了下面这个函数能实现动态更新,但是有两个弊端:componentWillReceiveProps: function(nextProps,nextState) { this.setState({ start_time: nextProps.start_time, end_time: nextProps.end_time, title: nextProps.title }); }1
2
3
4
5
6
7
一,倒不是代码量的问题,即使以后this.setState说不定会持续增多,但最主要的还是代码维护的问题,若采用了以前的方法,每次state的增减都要去维护componentWillReceiveProps这个方法。
二,以前的方法每次都会更新所有的组件,而有时候你不需要更新所有的组件。例如,在增加一项的时候,你并不需要更新其余项,此时你只需要给新的一样设置新的独一无二的key,而其余项key不变即能实现你的业务逻辑。举个例子吧。
render: function(){ var that = this; return( { this.state.items.map(function(word) { return <Object item={word} key={word.id + ":" + word.order + ":" + (word.color || "")} />; }) } ); }1
2
3
4
5
6
7
8
9
10
11
核心内容:
key={word.id + ":" + word.order + ":" + (word.color || "")}1
可见,只有id,order,color有改变的时候key才会改变,这大概就是key的意义所在吧。
相关文章推荐
- React学习-列表循环中的特殊属性key
- js入门·循环与判断/利用函数的简单实例/使用对象/列举对象属性的名称
- js循环map 获取所有的key和value的实现代码(json)
- js利用for in循环获取 一个对象的所有属性以及值的实例
- js如何将对象属性key-value变成字符串输出
- 浅谈React的diff算法和key属性
- js入门·循环与判断/利用函数的简单实例/使用对象/列举对象属性的名称
- JS一起学02:函数传参、操作属性第二种方式、提取行间事件、循环、this、焦点问题、联动选择、选项卡焦点图
- 用js动态的改变img标签里面的src属性实现图片的循环切换
- react文档阅读笔记----JSX属性
- 让js的forin循环禁止forin到某个属性的话要怎么做
- js定义对象循环拿到value和key
- 在jsp的c标签循环后台对象属性的情况下,使用js提取其中一个id属性使用ajax传到后台删除
- JS 利用 for in 循环获取 一个对象的所有属性以及值
- React.js点击获取自定义属性
- React-非dom属性-key
- js入门·循环与判断/利用函数的简单实例/使用对象/列举对象属性的名称
- javascript遍历json对象的key和任意js对象属性实例
- js 循环为对象添加属性及属性值
- js中json对象不规律key的遍历实现和json对象length属性的调用