资讯专栏INFORMATION COLUMN

react中key的正确使用方式

Wildcard / 2249人阅读

摘要:使用第一页张三李四王五第二页张三三李四四王五五翻页后,不变,子组件值发生改变,组件并不会被卸载,只发生更新。不推荐使用或者其他的第三方库来生成唯一值作为。

在开发react程序时我们经常会遇到这样的警告,然后就会想到:哦!循环子组件忘记加key了~

出于方便,有时候会不假思索的使用循环的索引作为key,但是这样真的好吗?什么样的值才是key的最佳选择?

为了弄明白,本文将从三个方面来分析"key":

1.为什么要使用key

2.使用index做key存在的问题

3.正确的选择key

1.为什么要使用key

react官方文档是这样描述key的:

Keys可以在DOM中的某些元素被增加或删除的时候帮助React识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。

react的diff算法是把key当成唯一id然后比对组件的value来确定是否需要更新的,所以如果没有key,react将不会知道该如何更新组件。

你不传key也能用是因为react检测到子组件没有key后,会默认将数组的索引作为key。

react根据key来决定是销毁重新创建组件还是更新组件,原则是:

key相同,组件有所变化,react会只更新组件对应变化的属性。

key不同,组件会销毁之前的组件,将整个组件重新渲染。

2.使用index做key存在的问题 2.1 受控组件

单纯的展示组件比如span,这些组件是受控组件,意味着他们的值将是我们给定好的。

如果子组件只是受控组件,使用index作为key,可能表面上不会有什么问题,实际上性能会受很大的影响。例如下面的代码:

// ["张三","李四","王五"]=>
  • 张三
  • 李四
  • 王五
// 数组重排 -> ["王五","张三","李四"] =>
  • 王五
  • 张三
  • 李四

当元素数据源的顺序发生改变时,对应的:

key为0,1,2的组件都发生了变化,三个子组件都会被重新渲染。(这里的重新渲染不是销毁,因为key还在)

相反,我们使用唯一id作为key:

// ["张三","李四","王五"]=>
  • 张三
  • 李四
  • 王五
// 数组重排 -> ["王五","张三","李四"] =>
  • 王五
  • 张三
  • 李四

根据上面的更新原则,子组件的值和key均未发生变化,只是顺序发生改变,因此react只是将他们做了移动,并未重新渲染。

2.2 非受控组件

像input这样可以由用户任意改变值,不受我们控制的组件,在使用了index作为key时可能会发生问题,看如下的栗子:

子组件:

  render() {
    return (
      

值:{this.props.value}

); } }

父组件

{
this.state.data.map((element, index) => {
    return 
    })
}

我们在前两个输入框分别输入对应的值:

然后在头部添加一个元素:

很明显,这个结果并不符合我们的预期,我们来分析一下发生了什么:

值:0

值:1

值:2

变化后:

值:5

值:0

值:1

值:2

可以发现:key 0,1,2并没有发生改变,根据规则,不会卸载组件,只会更新改变的属性。

react只diff到了p标签内值的变化,而input框中的值并未发生改变,因此不会重新渲染,只更新的p标签的值。

当使用唯一id作为key后:

值:0

值:1

值:2

变化后:

值:5

值:0

值:1

值:2

可以很明显的发现:key为 111,222,333的组件没有发生任何改变,react不会更新他们,只是新插入了子组件555,并改变了其他组件的位置。

3.正确的选择key 3.1 纯展示

如果组件单纯的用于展示,不会发生其他变更,那么使用index或者其他任何不相同的值作为key是没有任何问题的,因为不会发生diff,就不会用到key。

3.2 推荐使用index的情况

并不是任何情况使用index作为key会有缺陷,比如如下情况:

你要分页渲染一个列表,每次点击翻页会重新渲染:

使用唯一id:

第一页
  • 张三
  • 李四
  • 王五
第二页
  • 张三三
  • 李四四
  • 王五五

翻页后,三条记录的key和组件都发生了改变,因此三个子组件都会被卸载然后重新渲染。

使用index:

第一页
  • 张三
  • 李四
  • 王五
第二页
  • 张三三
  • 李四四
  • 王五五

翻页后,key不变,子组件值发生改变,组件并不会被卸载,只发生更新。

3.3 子组件可能发生变更/使用了非受控组件

大多数情况下,使用唯一id作为子组件的key是不会有任何问题的。

这个id一定要是唯一,并且稳定的,意思是这条记录对应的id一定是独一无二的,并且永远不会发生改变。

不推荐使用math.random或者其他的第三方库来生成唯一值作为key。

因为当数据变更后,相同的数据的key也有可能会发生变化,从而重新渲染,引起不必要的性能浪费。

如果数据源不满足我们这样的需求,我们可以在渲染之前为数据源手动添加唯一id,而不是在渲染时添加。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99438.html

相关文章

  • React

    摘要:语法是一种语法的拓展语言,在中官方也推荐使用描述用户界面,使用起来会比较快捷而且易读不是一门新的语言,可以理解为是一种语法糖,作用就是能够让我们更加直观的在中创建标签,最终还是会被编译为语法,例如我们看一段代码上面的语法最终会被编译为语法, Reatc JSX语法 jsx是一种JavaScript语法的拓展语言,在React中官方也推荐使用jsx描述用户界面,使用起来会比较快捷而且易读...

    techstay 评论0 收藏0
  • 【译】React应用性能优化

    摘要:应用主要的的性能瓶颈来自于一些冗余的程序处理以及组件中的的过程。为了避免这种情况,在你的应用中尽可能多的让返回。使用工具将帮助你找到应用程序中特定的性能问题。这个工具跟用起来很像,但是它是专门用来检测应用性能的。 这段时间对自己写的React应用的性能做了一些分析以及优化,发现项目中产生性能问题的原因主要来自两个方面: 大量的数据渲染使组件进行不必要的diff过程,导致应用卡顿; 部...

    txgcwm 评论0 收藏0
  • React元素与组件区别

    摘要:组件中有三种构建组件的方式。元素与组件的区别组件是由元素构成的。元素数据结构是普通对象,而组件数据结构是类或纯函数。使用才是操作元素的正确姿势。使用元素可以让用户传入自定义组件的同时,为组件添加属性。 在初学 React 的时候,分不清 React 组件和 React 元素,着实踩了一些坑。搞清楚 React 中什么是组件,什么是元素,既可以理清楚概念,也可以让你避免一些不必要的错误。...

    lifesimple 评论0 收藏0
  • ES6 + Webpack + React + Babel 如何在低版本浏览器上愉快玩耍(上)

    摘要:起因某天,某测试说这个页面在下白屏,也白。。某前端开发吭哧吭哧。。。一上午的时间就过去了,搞定了。第二天,某测试说又白了。。某前端开发吭哧吭哧。。。谁用的,出来我保证削不屎你。原谅我不禁又黑了一把。 起因 某天,某测试说:这个页面在 IE8 下白屏,9也白。。 某前端开发: 吭哧吭哧。。。一上午的时间就过去了,搞定了。 第二天,某测试说:IE 又白了。。 某前端开发: 吭哧吭哧。。。谁...

    you_De 评论0 收藏0
  • React / Vue 项目时为什么要在列表组件key,其作用是什么

    摘要:当正在更新使用渲染的元素列表时,它默认使用就地更新的策略。如果数据项的顺序被改变,将不会移动。避免对节点就地复用需要修改的节点位置没有改变,是内容更新了,这虽然提高了复用性能,但是往往在复杂的表单会导致状态出现错位。 当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用就地更新的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM。 元素来匹配数据项的顺序,而是就地更...

    eccozhou 评论0 收藏0

发表评论

0条评论

Wildcard

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<