React 的 Reconciliation 算法原理
React 的渲染机制 Reconciliation 过程

React 采用的是虚拟 DOM (即 VDOM ),每次属性 (props) 和状态 (state) 发生变化的时候,render 函数返回不同的元素树,React 会检测当前返回的元素树和上次渲染的元素树之前的差异,然后针对差异的地方进行更新操作,最后渲染为真实 DOM,这就是整个 Reconciliation 过程,其核心就是进行新旧 DOM 树对比的 diff 算法。
diff 算法
在某一时间节点调用 React 的
render()方法,会创建一棵由 React 元素组成的树。在下一次 state 或 props 更新时,相同的render()方法会返回一棵不同的树。React 需要基于这两棵树之间的差别来判断如何有效率的更新 UI 以保证当前 UI 与最新的树保持同步。
在上图第三部分,新旧DOM树比对所用的算法即 Diff算法

React diff策略
- Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。【永远只比较同层节点,不会跨层级比较节点。】
- 拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构。
- 对于同一层级的一组子节点,它们可以通过唯一 key 进行区分。
基于以上三个前提策略,React 分别对 tree diff、component diff 以及 element diff 进行算法优化,事实也证明这三个前提策略是合理且准确的,它保证了整体界面构建的性能。
执行流程(规则)
1、元素类型不相同时
直接将
原 VDOM 树上该节点以及该节点下所有的后代节点全部删除,然后替换为新 VDOM 树上同一位置的节点
当根节点为不同类型的元素时,React 会拆卸原有的树并且建立起新的树。当拆卸一棵树时,对应的 DOM 节点也会被销毁。组件实例将执行 componentWillUnmount() 方法。当建立一棵新的树时,对应的 DOM 节点会被创建以及插入到 DOM 中。组件实例将执行 componentWillMount() 方法,紧接着 componentDidMount() 方法。所有跟之前的树所关联的 state 也会被销毁。
2. 元素类型相同时
a. 都是 DOM 节点
React 会保留 DOM 节点,仅比对及更新有改变的属性。
<div className="old" title="老节点" /><div className="new" title="新节点" />
通过比对这两个元素,React 知道需要修改 DOM 元素上的 className 属性和 title 属性。
处理完该节点后,React 继续对子节点进行递归。
b. 都是组件元素
- 对于同一类型的组件,根据Virtual DOM是否变化也分两种,可以用shouldComponentUpdate()判断Virtual DOM是否发生了变化,若没有变化就不需要再进行diff,这样可以节省大量时间,若变化了,就按原策略进行比较
- 对于非同一类的组件,则将该组件判断为 dirty component,从而替换整个组件下的所有子节点。
当一个组件更新时,组件实例保持不变,这样 state 在跨越不同的渲染时保持一致。React 将更新该组件实例的 props 以跟最新的元素保持一致,并且调用该实例的 componentWillReceiveProps() 和 componentWillUpdate() 方法。











![分布式文件存储系统FastDFS[3]-通过Docker安装并且从客户端进行上传下载测试](https://img-blog.csdnimg.cn/c53df8d8240948b0a3894966c0ced8fa.png)







