从新学习 React (二) Diffing 算法

前几天面试问道 react 的相关知识,对我打击比较大,感受对 react 认识很是肤浅,因此在这里从新梳理一下,想一想以前没有仔细思考过的东西。html

另外有说的不对的地方还请帮我指正一下,先谢谢各位啦。react

目录索引:面试

背景

咱们知道,React 执行 Render() 函数时,会生成一次虚拟 DOM,当组件再次更新时,会再生成一颗新的树,而后 React 会对比两棵树的异同,执行更新算法。React 经过以下方法比较 DOM 的异同,其复杂度为 O(n):算法

  • 两个不一样类型的元素会产生出不一样的树
  • 开发者能够经过 key prop 来暗示哪些子元素在不一样的渲染下能保持稳定

Diffing 算法

当对比两颗树时,React 首先比较两棵树的根节点。不一样类型的根节点元素会有不一样的形态。redux

比对不一样类型的元素

当根节点为不一样类型的元素时,React 会拆卸原有的树而且创建起新的树。举个例子,当一个元素从 <a> 变成 <img> 或者 DOM 节点被销毁,都会触发一个完整的重建流程。数组

比对同一类型的元素

当比对两个相同类型的 React 元素时,React 会保留 DOM 节点,仅比对及更新有改变的属性。性能优化

以下所示,当更新 style 属性时,React 仅更新有所更变的属性,而 title 属性不会被修改。函数

<div className="before" title="stuff" />
<div className="after" title="stuff" />
复制代码

比对同类型的组件元素

当一个组件更新时,组件实例保持不变,这样 state 在跨越不一样的渲染时保持一致。React 将更新该组件实例的 props 以跟最新的元素保持一致,而且调用该实例的 componentWillReceiveProps() 和 componentWillUpdate() 方法。源码分析

key

若是一个列表没有 key 值,一旦数组增长或者删除,react 就没法知道那些元素是不变的,那些的改变了的。可是当子元素拥有 key 时,React 使用 key 来匹配原有树上的子元素以及最新树上的子元素。如下例子在新增 key 以后使得以前的低效转换变得高效:post

<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>
复制代码

如今 React 知道只有带着 '2014' key 的元素是新元素,带着 '2015' 以及 '2016' key 的元素仅仅移动了。

结语

关于 key 值,必定要知道其做。本身在写代码的时候尽可能不要采用 index 或者随机数做为 key,由于这样不但没有得到 react 优化算法的加持,并且会让本身的数据出现错乱。

相关文章
相关标签/搜索