redux高阶运用
2017-08-26 本文已影响24人
星月西
1. diff算法
React组件的核心思想是:
- 将页面拆分为一个个组件,一个组件还可能嵌套更小的组件,每个组件都有自己的数据,当某个组件的数据发生变化时,更新该组件的部分视图。
- 更新的过程是由数据驱动的,新的数据自该组件顶层向下流向子组件,每个组件调用自己的render方法得到新的视图,并与之前的视图diff比较差异,完成更新,这个过程就是reconciliation-调和
虚拟DOM基本原理:
用纯js对象来模拟DOM树,每当更新时,根据组件的render方法计算出新的虚拟DOM树,并与之前的虚拟DOM树作比较,得到一个差异补丁,最后隐射到真正的DOM树上完成视图更新,以减少操作DOM的次数
diff算法:前端很少跨越层级移动DOM元素,只会对虚拟DOM中同一层级的元素进行比较,这样算法复杂度就可以达到O(n)
diff碰到列表会有问题
发现列表元素不同时,就会对其进行重渲染,但是可能只是进行了插入操作,只需要进行移动操作即可,需要定义key属性,diff时就会去查找是否有相同的key元素,比较它们是否完全相同,若是则会复用该元素,免去不必要的操作
不推荐使用数组的index作为key,因为如果数据重排,index并不能起到唯一标识的作用,每次视图元素都会重新渲染
diff会帮我们计算出虚拟DOM中真正变化的部分,并只针对该部分进行原生DOM操作,而非重新渲染整个页面,从而保证了每次操作更新后页面的高效渲染
传统diff算法循环递归对节点进行依次比较,算法复杂度为O(n3),React可以转化为O(n)复杂度
2.diff策略
diff算法的三个策略
- DOM节点的跨层级的移动操作特别少,可以忽略不计
- 拥有相同类的两个组件会生成相似的树形结构,拥有不同类的两个组件会生成不同的树形结构
- 对于同一层级的一组子节点,它们可以通过唯一id进行区分
2.1 tree diff
对树进行分层比较,两棵树只会对同一层次的节点进行比较,即同一个父节点下的所有子节点,当发现节点已经不存在时,则该节点及其子节点会被完全删除掉,不会用于进一步的比较,这样只需要对树进行一次遍历
当出现节点跨层级移动时,并不会出现想象中的移动操作,而是移除不存在的节点及其子节点,创建存在的节点
注意:在开发组件时,保持稳定的DOM结构会有助于性能的提升,可以通过CSS隐藏或显示节点,而不是真正移除或添加DOM节点
2.2 component diff
组件间比较:
- 同一类型组件,按照原策略继续比较虚拟DOM树
- 将该组件判断为dirty component,替换整个组件下的所有子节点
- 同一类型组件,可能虚拟DOM完全没有变化,用户通过shouldComponentUpdate来判断组件是否需要进行diff算法
即不同组件则,直接替换掉组件下的所有子节点