@H_403_1@React提供给我们声明式的@H_403_1@API以至于我们根本不需要关心@H_403_1@React内部到底做了什么,这让我们写代码变得轻松,但是我们还是非常有必要了解@H_403_1@React内部实现机制,这对我们自己开发一个公司框架以及深入学习@H_403_1@React是非常有帮助的。
这一篇博客就是深入的讲解@H_403_1@React的更新机制也属于React的调解器知识点,打开你内心世界@H_403_1@React的大门,让我们见识见识@H_403_1@diff算法的魅力吧,骚年们!
1.算法魅力
之前将性能优化的时候已经提到过基本的更新流程,@H_403_1@render进行视图渲染,然后@H_403_1@React检查是否发生变化,发生了就更新。
有一些一般的算法以最小的代价更新一棵树为另外一棵树,即便是最好的算法它也是
当我们在@H_403_1@React用前面那种算法的话,就单单
这个启发式算法的使用基于以下两点:
2.@H_403_1@Diff算法
类型不同
在比较两颗树时,@H_403_1@React首先比较这两颗树的根节点,至于判断不同就是判断他们的相应的状态和数据了
如果两个元素的类型不同的话,@H_403_1@React会抛弃旧的树,构造新的树,比如说从@H_403_1@<a>变到了@H_403_1@<img>,@H_403_1@<article>变到了@H_403_1@<comment>,@H_403_1@<button>变到了@H_403_1@<div>,这些变化都会造成一个全新的树的构建,记住是以当前节点为根,完全重新建立,而不是单单更新根节点。
当摧毁旧树时,组件会调用@H_403_1@componentWillUnmount()进行摧毁自身,当建立新的输时,会调用@H_403_1@componentWillMount()处理,接着就是@H_403_1@componentDidMount()处理,这里注意@H_403_1@componentWillUnmount和@H_403_1@componentWillMount的区别
这种更新方式会导致子树的所有节点状态摧毁,重新进行建立
<div>
<Counter />
</div>
<span>
<Counter />
</span>
类型相同
当类型相同时,@H_403_1@React会看他们的属性,然后更新要更改的属性
<div className="before" title="stuff" />
<div className="after" title="stuff" />
这样,@H_403_1@React只会去修改节点的@H_403_1@className属性,而不会去更改其他的地方
当处理完这一层节点后,@H_403_1@React就会递归去处理它们的子节点
特提:处理类型相同的组件
当是比较类型相同的组件时,@H_403_1@React调用@H_403_1@componentWillReceiveProps和@H_403_1@componentWillUpdate函数进行处理(这两个函数后续会讲解),然后直接使用@H_403_1@render函数,接着又是@H_403_1@diff算法处理
3.对于列表孩子的处理
每当他们的父亲节点不同时,@H_403_1@React就会处理出孩子列表,然后进行更新。
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
当时如果我们只是在孩子节点后面直接插入一个@H_403_1@<li>chird</li>,它只会直接处理。
可是请看下面例子
<ul>
<li>Duke</li>
<li>Villanova</li>
</ul>
<ul>
<li>Connecticut</li>
<li>Duke</li>
<li>Villanova</li>
</ul>
这会更新所有的孩子节点,效率就比较低了
4.@H_403_1@keys优化
为了解决@H_403_1@3最后更新所有孩子节点的问题,@H_403_1@React就提供了一个@H_403_1@key属性,这个属性,之前将列表的时候就说过了,维护一个@H_403_1@key比维护一个@H_403_1@li标签更好。
<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>
这样@H_403_1@React直接就知道@H_403_1@key=2014是一个新的元素,而@H_403_1@key=2015和@H_403_1@key=2016则会往后移。
这其中的@H_403_1@key要是唯一的,你可以是对象自己提供的,也可以用数组的索引,优劣在列表章节已经说了。
5.权衡
了解算法的实现是非常重要的,这样我们就可以更加深入的了解@H_403_1@React处理的每一个细节,从而可以去优化性能.
当然,处理事件的时候一般会遇到这么两个问题
如果两者相似,应该作为不同处理,构造出不同的树
@H_403_1@key值要具有唯一性,否则会造成子组件的丢失
这两个就是上面说的启发式处理的前提条件。