通过阅读React的文档我们知道React这个框架的核心思想是,将页面分割成一个个组件,一个组件还可能嵌套更小的组件,每个组件有自己的数据(属性/状态);当某个组件的数据发生变化时,更新该组件部分的视图。更新的过程是由数据驱动的,新的数据自该组件顶层向下流向子组件,每个组件调用自己的render方法得到新的视图,并与之前的视图作diff-比较差异,完成更新,这是react实现的diff算法。这个过程就叫作reconciliation-调和。

React通过virtual dom来实现高效的视图更新。基本原理是用纯js对象模拟dom树,每当更新时,根据组件们的render方法计算出新的虚拟dom树,并与此前的虚拟dom树作diff,得到一个patch(差异补丁),最后映射到真实dom树上完成视图更新。而两棵树的完全的 diff 算法是一个时间复杂度为 O(n^3)的问题。但是在前端当中,很少出现跨越层级移动DOM元素的情况,所以React采用了简化的diff算法,只会对virtual dom中同一个层级的元素进行对比,这样算法复杂度就可以达到 O(n)。

由于React采用的diff算法是对新旧虚拟dom树同层级的元素挨个比较,碰到循环输出的元素时会有一些问题,比如列表。先来看一个例子:

1
2
3
4
5
6
7
8
9
10
11
// 旧v-dom
<ul>
<li>first</li>
<li>second</li>
</ul>
// 新v-dom
<ul>
<li>zero</li>
<li>first</li>
<li>second</li>
</ul>

React在diff两棵树时,发现原来的两个li元素都与新v-dom中对应位置上的两个li元素不同,就会对其修改,并向真实dom树中插入新的second节点。实际上,我们可能只是进行了在first之前插入新zero节点的操作,而现在进行了额外的修改操作。
React官方文档提示我们应该使用key属性来解决上述问题。key是一个字符串,用来唯一标识同父同层级的兄弟元素。当React作diff时,只要子元素有key属性,便会去原v-dom树中相应位置(当前横向比较的层级)寻找是否有同key元素,比较它们是否完全相同,若是则复用该元素,免去不必要的操作。
延续第一个例子,如果每个li元素都有key属性:

1
2
3
4
5
6
7
8
9
10
11
// 旧v-dom
<ul>
<li key="1">first大专栏  React中key的讲解g"></li>
<li key="2">second</li>
</ul>
// 新v-dom
<ul>
<li key="0">zero</li>
<li key="1">first</li>
<li key="2">second</li>
</ul>

现在React就知道了,新增了key为”0”的元素,而”1”与”2”仅仅移动了位置。
key必须是字符串类型,它的取值可以用数据对象的某个唯一属性,或是对数据进行hash来生成key。

1
2
3
<ul>
{list.map(v=> <li key={v.idProp}>{v.text}</li>)}
</ul>

但是强烈不推荐用数组index来作为key。如果数据更新仅仅是数组重新排序或在其中间位置插入新元素,那么视图元素都将重新渲染。来看下例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
<ul>{list.map((v,idx)=><li key={idx}>{v}</li>)}</ul>
// ['a','b','c']=>
<ul>
<li key="0">a</li>
<li key="1">b</li>
<li key="2">c</li>
</ul>
// 数组重排 -> ['c','a','b'] =>
<ul>
<li key="0">c</li>
<li key="1">a</li>
<li key="2">b</li>
</ul>

React发现key为0,1,2的元素的text都变了,将会修改三者的html,而不是移动它们。

React中key的讲解的更多相关文章

  1. 【react】---react中key值的作用

    一.React中key值得作用 react中的key属性,它是一个特殊的属性,它是出现不是给开发者用的,而是给React自己使用,有了key属性后,就可以与组件建立了一种对应关系,简单说,react利 ...

  2. vue中:key 和react 中key={} 的作用,以及ref的特性?

    vue中:key 和react 中key={} 为了给 vue 或者react 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性 一句话概括就是 ...

  3. React中key的必要性与使用

    React这个框架的核心思想是,将页面分割成一个个组件,一个组件还可能嵌套更小的组件,每个组件有自己的数据(属性/状态);当某个组件的数据发生变化时,更新该组件部分的视图.更新的过程是由数据驱动的,新 ...

  4. react中key值的理解

    react利用key来识别组件,它是一种身份标识标识,相同的key react认为是同一个组件,这样后续相同的key对应组件都不会被创建有了key属性后,就可以与组件建立了一种对应关系,react根据 ...

  5. react中key的使用

    面试题: 1). react/vue中的key的作用/内部原理 2). 为什么列表的key尽量不要用index 虚拟DOM的key的作用? 1). 简单的说: key是虚拟DOM对象的标识, 在更新显 ...

  6. React之事件绑定、列表中key的使用

    在学习React的Hadding Events这一章节,发现事件回调函数的几种写法,看似区别不大,但实际差异还是蛮大的. class Toggle extends React.Component{ c ...

  7. React 中的key值

    在react中必须要有key值,key不是用来提升react的性能的,react中的key属性,它是一个特殊的属性,它是出现不是给开发者用的(例如你为一个组件设置key之后不能获取组件的这个key p ...

  8. 谈谈Vue/React中的虚拟DOM(vDOM)与Key值

    谈谈Vue/React中的虚拟DOM(vDOM)与Key值 一.DocumentFragment 在了解虚拟DOM前,先来了解DOM的一个对象属性--DocumentFragment. 在一次操作中, ...

  9. react中使用redux简易案例讲解

    为什么我想要使用redux? 前段时间初步上手了react,最近在使用react的过程中发现对于组件之间通信的需求比较迫切,尤其是在axios异步请求后端数据的时候,这样的需求是特别强烈的!举个例子: ...

随机推荐

  1. 阿里云Linux格式化数据盘,分区并挂载一个文件系统

    阿里云一块全新的数据盘挂载到ECS实例后,您必须创建并挂载至少一个文件系统.本示例使用I/O优化实例,操作系统为CentOS 7.6,为一块新的300GiB数据盘(设备名为/dev/vdb)创建一个M ...

  2. Python笔记_第三篇_面向对象_4.单下划线和双下划线

    说道这里我们需要稍微暂停一下.前面我们说到了类是作为一个对象存放容器.这个容器里面有属性和方法.最好的理解类的方式就是把类想想成一个容器. 然后构造了一个析构函数和构造函数,然后又对object和se ...

  3. [Python]安装和运行flask框架

    随着你的 Python 项目越来越多,你会发现不同的项目会需要 不同的版本的 Python 库.同一个 Python 库的不同版本可能不兼容.虚拟环境可以为每一个项目安装独立的 Python 库,这样 ...

  4. Please select an empty folder to install Android Studio

    原因 当前安装的Android Studio的文件夹不是空的 解决 把路径改成一个空文件夹即可

  5. E - Ingredients 拓扑排序+01背包

    题源:https://codeforces.com/gym/101635/attachments 题意: n行,每行给定字符串s1,s2,s3代表一些菜谱名.s2和s3是煮成是的必要条件,然后给出c和 ...

  6. c语言中,为什么以下程序直接按”Enter“也就是回车程序不结束?

    /************************************************************************* > File Name: system.c ...

  7. 手机APP例如抖音,让 people‘s 注意力集中到了 社会进化的 优胜部分 (优胜劣汰,什么是优) + 真善美,的 “美” , 促进了2极分化, 会产生强者俞强,弱者越弱,确实促进了信息的流通,传播了有用的东东 产生了独特的价值 而 如何 能计算出这些价值呢, 需要 数学 金融 财务 货币 量化吗

    手机APP例如抖音,让      people‘s  注意力集中到了  社会进化的 优胜部分  (优胜劣汰,什么是优)   +     真善美,的  “美”        , 促进了2极分化, 会产生 ...

  8. 用@font-face应用自定义字体

    @font-face格式 @font-face { font-family: <YourWebFontName>; src: <source> [<format>] ...

  9. Eclipse 热部署方式

    1.tomcat 热部署 1.1方法一:更改 server.xml,更改为 <Context docBase="dreamlive" path="/ROOT&quo ...

  10. OC门与OD门以及线与逻辑

    OC(Open Collector)门又叫集电极开路门,主要针对的是BJT电路(从上往下依次是基极,集电极,发射极)OD(Open Drain)门又叫漏极开路门,主要针对的是MOS管(从上往下依次是漏 ...