react diff 学习 之 component diff

所谓的diff算法,其实就是react 同时比较两棵虚拟dom树之间的差异,一颗是当前的dom结构,另一棵在react状态变更将要重新渲染时生成。react通过比较这两棵树的差异,决定是否需要修改dom结构,以及如何修改。并且,最大程度的复用旧的节点,来减少真实的dom渲染。在这个过程中进行比较的算法称作diff算法。(react 16之前)

这里有个疑问,为什么虚拟dom之间还要进行比较,直接把旧的虚拟dom替换为新的虚拟dom不就行了?

可能是因为直接全部替换,要对整棵虚拟dom树进行layout布局,计算,开销太大了,而只对需要更新的某一部分dom进行替换,性能更好。

流程第一步,直接把vdom全部转成fiber。不需要diff

二、更新阶段,拿到了新的虚拟dom树后,要比较,怎么来修改dom

在fiber里面就是怎么生成新的fiber树,然后fiber又转换为dom

这里有一个疑问,为什么双缓冲树章节,说的是直接替换呢?

为什么react 的diff相较于传统的diff性能提升了很多呢?

答:通过三大策略完成了优化,就是我这篇文章所介绍的tree diff , component diff , element diff 。不过这里得注意。这些是react16.8之前的版本的优化策略,16.8之后改用了fiber架构有些地方就不一样了。

component diff是专门针对更新前后的同一层级间的react组件比较diff,注意,是组件间的比较。

有两种情况,同一类型组件,和不是同一类型。

1. 如果是同一类型的组件,按照原策略继续比较virtual dom树(例如继续比较组件props和组件的子节点及其树形)

2. 如果不是,则判断该组件为dirty component(脏组件),从而替换整个组件下去的所有子节点,即销毁原组件,创建新组件。

3. 对于同一类型的组件,有可能起virtual dom没有任何变化,如果能够确切的知道这点,那么就可以节省大量的diff运算时间。因此,react允许用户通过shouldComponentUpdate()来判断该组件是否需要进行diff运算。

shouldComponentUpdate是怎么使用的呢?

它接收三个参数

shouldComponentUpdate(newProps,newState,nextContext),前面两个参数不解释,第三个参数是新的context。

shouldComponentUpdate(newProps,newState){
    if(newProps.a !== this.props.a ){ /* props中a属性发生变化 渲染组件 */
        return true
    }else if(newState.b !== this.props.b ){ /* state 中b属性发生变化 渲染组件 */
        return true
    }else{ /* 否则组件不渲染 */
        return false
    }
}

那么问题来了,在函数组件中,有没有类似于sholdComponentUpdate的功能呢?

还真有,那就是memo的第二个参数compare函数。

下面我们来简单介绍下memo的使用

React.memo(Component,compare)

memo的第一个参数,需要被包裹的组件。第二个参数compare函数如果不写的话,就会用浅比较的原则处理props,相当于仅比较props版本的pureComponent。

function compare(pre,next){
    // return true或者false      
}

compare函数和shouldComponentUpdate规则完全一样。返回true就更新组件,返回false就不更新。接收两个参数,第一个时更新之前的props,第二个是更新之后的props.用这两个进行比较。

参考:

 在函数组件中,如何实现shouldComponentUpdate()_react 函数组件 shouldcomponentupdate-CSDN博客

React 进阶实践指南 - 我不是外星人 - 掘金小册 (juejin.cn)

浅谈React 虚拟DOM,Diff算法与Key机制参考文章: https://juejin.cn/post/68449 - 掘金

posted @ 2024-09-03 12:19  飞向火星  阅读(47)  评论(0编辑  收藏  举报