说说Real diff算法是怎么运作的?
diff算法
在某一时间节点调用
React
的render
() 方法,会创建一棵由React
元素组成的树。在下一次state
或props
更新时,相同的render
() 方法会返回一棵不同的树。React
需要基于这两棵树之间的差别来判断如何有效率的更新 UI 以保证当前UI
与最新的树保持同步。
React diff策略
Web UI
中DOM
节点跨层级的移动操作特别少,可以忽略不计。【永远只比较同层节点,不会跨层级比较节点。】- 拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构。
- 对于同一层级的一组子节点,它们可以通过唯一
key
进行区分
基于以上三个前提策略,React 分别对 tree diff
、component diff
** 以及 element diff
进行算法优化,事实也证明这三个前提策略是合理且准确的,它保证了整体界面构建的性能。
tree层:
tree
层对DOM
节点的跨层级移动的操作忽略不计,只对相同层级的DOM
节点进行比较(即同一个父节点下的所有子节点),一旦发现节点不存在,直接删除掉该节点以及之下的所有子节点。
component层:
component
层是组件间的比较,有三种策略:
- 遇到同一类型的组件遵循
tree diff
,进行层级对比 - 遇到不同类型的组件,直接将这个不同的组件判断为脏组件,并替换该组件和之下所有的子节点
- 在同一类型的两个组件中,当知道这个组件的虚拟
dom
没有任何变化,就可以手动使用shouldComponentUpdate
()来判断组件是否需要进行diff
,进一步的提升了diff
效率和性能
注意:
避免使用结构相同但是类型不同的组件,由于类型不同的原因,diff
会直接销毁该组件并重建,会造成的性能浪费;
对于同一类型并且没有变化的组件,合理使用 shouldComponentUpdate
() 进行优化
element层:
element层对同一层级的元素节点进行比较,有三种情况:
- 面对全新的节点时,执行插入操作
- 面对多余的节点时,执行删除操作
- 面对换位的节点时,执行移动操作
react中key值的作用
key值就是每个元素节点对应的唯一标识,要进行数据的更新,需要进行新旧虚拟dom的对比,就需要对比子元素的key值是否有匹配项,如果有则会进行数据的更新;如果没有就需要进行删除和重新创建