React中的key

前言:( ⊙ o ⊙ )啊!最近简历投得很不顺利呀,感觉是项目经验不符合互联网公司的需求........╮(╯▽╰)╭没办法,在公司做得最多的就是业务逻辑的代码,虽然知道这一点,自己在加紧学习,但是结果还是不尽如人意,毕竟没做过真正的项目别人是很少会"冒险".......也罢,《盗钥匙的方法》中的”杀手“成了我目前的一个”精神“支柱!

在参考官网的文档学习React中,其实有关于key的讲解,但是自己觉得有点晦涩,当时就没怎么看;到后来在做一个例子的时候:商品的表格,提供了简单的查询功能;我在自己实现的过程中,发现”key“这个关键词在react中是比较重要的一个概念,而且后面自己想对价格排序的时候发现在这个"key"上屡屡受挫,只好自己总结一下了。(出来混,总得要还的呀!)


github:https://github.com/liuzaijiang/React-text

我相信大部分人都是参考网上的这篇文章学习的:http://taobaofed.org/blog/2016/08/24/react-key/


一千个读者就有一千个哈姆雷特嘛,我也来学习学习!

首先是概念:

React 元素可以具有一个特殊的属性 key,这个属性不是给用户自己用的,而是给 React 自己用的。如果我们动态地创建 React 元素,而且 React 元素内包含数量或顺序不确定的子元素时,我们就需要提供 key 这个特殊的属性。(大多我们用的地方是渲染数组中的元素,例如表格,li等)



OK,接下来是我根据官网例子加上自己的实现,对于这个key的理解。

在官网,有个例子中就是渲染一个商品的价格表格,你打开F12后会发现:

Warning: flattenChildren(...): Encountered two children with the same key

是因为每个td是放在一个数组中,但是并没有给每个td赋一个唯一的key值属性解决方法就是:

rows.push(<ProductRow product={product} key={product.name} />);

我这里赋的key是每个商品的name(唯一),不管赋什么都是要保证一个唯一性;(当然还要有一定的技巧性,这个后面操作表格数据的时候会用到。)


这个key值是用来干嘛的呢?

当我们组件状态更新后,会重新渲染组件,渲染组件的时候会一个个去根据key值的情况去渲染:

A. 渲染前的key值存在,则去寻找这个key值对应的组件:

a.组件数据不变,则不重新渲染这个组件;

b.若组件数据改变,则渲染改变的这一部分数据;

B.渲染前的key值不存在,则会销毁这个key值对应的组件:

C.出现新的key值,则渲染一个新的key值对应的组件;



有了上面的这些总结,其实我们就可以对表格进行操作了:增,删,改。


增:

如果想增加一个商品,我们只需要在保存商品的数组中增加这个商品的对象即可,然后为这个数据去添加一个新的key值,这样状态改变的时候就会把这个新商品渲染进表格;


删:

如果想删除一个商品,我们只需要将这个商品在这个数组中去掉,这样key值也会随之没有,渲染的时候这个商品也不会渲染出来;不过我们怎么去寻找到这个商品呢?

这里我们就要利用到key值的一个技巧,上面提到了我给每个商品的 key值赋值的是每个商品的name(唯一),一般都来说都是赋的是index值,就是每个商品在数组中存在的索引值。但是这样不好,为什么?因为我们商品会去排序,这样你的顺序就会被打乱。如果是用name值得话,我们可以很精确的找到,然后配合filter方法来筛选出被删除后的数组。

而且我们是不能通过this.props.key获取这个key值的,所以这里就再为组件定义一个属性,赋值name,这样我们获得这个属性的值,就相当于获得了key值。


流程:首先我们在渲染的时候给每个商品的"删除功能的td元素上"赋值一个name属性,值就是我们的商品name;

然后我们通过click事件的回调函数中的参数event来获取这个name值,event.target.name;

再把这个值在商品的数组中通过filter方法,来筛选出除了这个值的其他商品,这样剩下的就是被删除后的数组,我们需要渲染的商品;

最后更新一下状态,渲染表格;


改:

修改商品和我们删除商品其实大致思路是一样的,只不过稍微多了一些步骤,当我们用filter筛选出了我们需要修改的对象的时候,同时还需要获得它在这个数组中的index(索引),然后再修改其数据,更新状态。


当然,我们修改商品的时候我这边是弹出一个框,然后还需要把商品本身的情况先进行赋值,我们这里需要用到ref这个属性获取我们真实的DOM节点,比如<input/>这些,但是这里需要注意的就是,ref在render中是无法使用的,因为必须要等组件挂载后才能获取到值,那我们如何为组件预先赋值呢?很简单,使用defaultValue这个属性

<input ref='modifyCategory' id='staffModifyName' type='text' defaultValue={modifyProduct[0].category}/>
这样就行,这个是修改商品,如果是新加商品的话,我们还是用value就行了。



额外:

如果每次渲染的时候想每个组件都刷新(重新渲染)的话,就给这个key值赋一个变量;

rows.push(<ProductRow product={product} key={+new Date() + i} />);

一个当前时间加索引,这样每次状态变化的时候,组件都会去重新渲染。


官网提供的那个表格的例子其实比较简陋,还有一个BUG:


let product = [
{category: 'Sporting Goods',price: 49.99,stocked: true,name: 'Football'},
{category: 'Sporting Goods',price: 9.99,name: 'Baseball'},price: 29.99,stocked: false,name: 'Basketball'},
{category: 'Electronics',price: 99.99,name: 'iPod Touch'},price: 399.99,name: 'iPhone 5'},price: 199.99,name: 'Nexus 7'}
];


仔细可以发现,它的商品类别category都是分类好了,按顺序写进了数组,然后表格显示的时候是

Sporting Goods

xxxxx

xxxxx

xxxxx

Electronics

xxxxx

xxxxx

xxxxx


每个商品种类也是一行,这样也会有一个key值,如果把数组的顺序打乱的话,会出现下面这种情况,而且它的商品种类的key都是用的商品的category,这样会出现key值不唯一的情况,我解决了key值不唯一的情况,这个排列有问题的还没有解决,而且做价格排序的话也很有值得思考的地方,到底是按所有商品的价格排序,还是按每个种类的商品排序呢?值得去思考


Sporting Goods

xxxxxx

xxxxxx

Electronics

xxxxxx

xxxxxx

xxxxxx

Sporting Goods

xxxxxx

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...