前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【React总结(一)】浅谈 React 中 key

【React总结(一)】浅谈 React 中 key

原创
作者头像
志航
修改2019-03-08 19:03:08
1.4K0
修改2019-03-08 19:03:08
举报
文章被收录于专栏:前端探索前端探索前端探索

上周在处理项目的时候,由于之前项目中引用的是 cdn 中的生产环境的 React 所以导致所有在开发环境中应该暴露的 warnning 都被屏蔽了,上周修改了 webpack 的配置把 React 改为 develop 的时候,就出现了一堆下列的报错:

Warning: Each child in an array or iterator should have a unique "key" prop. 

意思是: 数组或迭代器中的每个子元素都应该有一个唯一的“key”属性。

解决的方法和能见到,就是为数组中的元素传递一个唯一的key(例如list的唯一id),就可以很好地解决这个问题。由于这个是一个 warning ,很多同学在开发中可能会忽略或者是屏蔽调这样一个警告,那究竟加不加这个 key 属性会有什么不一样?它的作用又是什么。

React 中的 element diff 算法

当在数组或者迭代器中循环渲染元素的时候,其实是用到了 React 的 element diff 算法,,当节点处于同一层级时,React diff 提供了三种节点操作,分别为:INSERT_MARKUP(插入)、MOVE_EXISTING(移动)和 REMOVE_NODE(删除)。

举个例子,有以代码,

// props.dataLists = ['a', 'b', 'c', 'd'];
const dataList = props => {
    <div>
        props.dataLists.map(value=><div key={value}>{value}</div>)
    </div>
}

当现在由外部传入的dataLists修改为 ['b','a','d','c'] 的时候,此时,如果按照原始的diff算法,对比旧的props.dataLists = ['a', 'b', 'c', 'd'];,发现 第一个位 b != a,则创建并且插入 b 到新的集合里面,删除老得a(这里我们假设 abcd 也代表一个element)如此类推,创建插入了 a,d,c删除了b,c,d;

old:  a, b, c, d
new: b, a, d, c

假设这里有10000个 elements, 这里的开销大到不能想象,而且仔细的你可能已经发现了,其实上面的 element并没有发生变化,他们仅仅是发生了位置的变化,但是却产生了非常大开销的删除、创建和删除操作,说白了,其实我们只要交换以下几个 element 的位置就好了。

所以,针对这样一个优化,React 提出了这样的优化策略。

允许开发者对同一层级的同组子节点,添加唯一 key 进行区分

新老集合所包含的节点,老集合进行 diff 差异化对比,通过 key 发现新老集合中的节点都是相同的节点,因此无需进行节点删除和创建,只需要将老集合中节点的位置进行移动,更新为新集合中节点的位置,此时 React 给出的 diff 结果为:b、d 不做任何操作,a、c进行移动操作,即可。

另外,看 Babel 转换 jsx 后,也很好理解为什么通过 key 可以分辨出 变化前后 element 的关系,为什么只有数组需要key。

// before babel 
const dataList = props => {
    <div>
      <div>
        <h1>hello world</h1>
        {[
        <div key={1}>1</div>,
       <div key={2}>2</div>
        ]}
      </div>   
    </div>
}

// afer babel
"use strict";

"use strict";

var dataList = function dataList(props) {
  React.createElement(
    "div",
    null,
    React.createElement(
      "div",
      null,
      React.createElement("h1", null, "hello world"),
      [
        React.createElement(
          "div",
          {
            key: 1
          },
          "1"
        ),
        React.createElement(
          "div",
          {
            key: 2
          },
          "2"
        )
      ]
    )
  );
};

不管 props 的变化,数组外的每个元素失踪出现在 React.createElement 参数列表中的固定位置不变,这个位置就是天然的 key。

另外我也发现,当使用 react-router 的时候,通常 route 和 redirect 也要给 key 赋值

参考资料:

React 源码剖析系列 - 不可思议的 react diff

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • React 中的 element diff 算法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档