react性能优化

一.React更新机制

1. react的渲染流程:

JSX
虚拟DOM
真实DOM

(1 ES6的JSX语法会通过babel转换成React.createElement()函数的调用并生成ReactElement对象 组成 对象树(js对象 即 虚拟DOM);
(2 通过ReactDOM.render让 虚拟DOM 和 真实DOM同步起来(将虚拟DOM渲染成真实DOM),这个过程中叫做协调(Reconciliation);

采用虚拟DOM,而不是直接修改真实DOM的原因:
(1) 很难跟踪状态发生的改变;
(2) 操作DOM性能较低,传统的开发模式会进行频繁的DOM操作, 会引起浏览器的回流和重绘, 虚拟DOM可以对多次操作进行合并;
(3) 虚拟DOM帮助我们从命令式编程转到了声明式编程的模式(我们开发者只需要告诉React希望UI是什么状态,React来确保DOM和这些状态是匹配的,开发者就可以从手动更改DOM,属性操作,事件处理中解放出来)

2. react 的更新流程:

props/state改变
render函数重新执行
产生新的DOM树
新旧DOM树进行diff
计算出差异进行更新
更新到真实的DOM

react-diff算法过程:
(1) 同层节点之间进行相互比较,不会跨层级比较;
(2) 情况一: 同一层级 不同类型节点,React会拆卸掉对应的旧的整个节点树,并建立起新的节点树; 销毁时会触发componentWillUnmount(),新建和插入时触发componentWillMount() 方法, 紧接着 componentDidMount() 方法;

如下:在这里插入图片描述

(3) 情况二:对比同一类型的元素, React会保留DOM节点,仅比对及更新有改变的属性,例如className,style…

在这里插入图片描述

(4) 情况三:同一类型的组件元素,组件会保持不变;

  • react会更新该组件的props,并调用componentWillReceiveProps() 和 componentWillUpdate() 方 法;
  • 下一步,调用render()方法,diff算法将在之前的结果以及新的结果中进行递归;

(5) 对子节点进行递归 , 及列表遍历过程;

  • 当递归DOM节点的子元素时,React会同时遍历两个子元素列表,当产生差异时,生成一个mutation;
    在这里插入图片描述
    在最后插入一条数据情况: 前面两个比较完全相同,不会产生mutation;最后一个会产生,将其插入到新的DOM树中即可;
    在这里插入图片描述
    在最上面插入一条数据情况:React会对每个子元素产生一个mutation,而不是保持原有的元素不变,因为diff过程是从第一个开始逐个进行比较的,所以每个元素相当于都是新的;
    这种方式会带来一定的性能问题,因此key的优化出现了;

二.key的优化

上面列表数据遍历插入方式不同对key的需求也就不同了;

方式一:在最后位置插入数据, 有无key对于优化的意义不大;

方式二:在前面插入数据,
没有key的情况下,所有的元素都需要进行修改;
有key时, React使用key来匹配 原有树上的子元素以及最新树上的子元素,旧的元素仅仅进行移位,不需要进行任何的修改;

key的注意事项:
(1) key 应该是唯一的;
(2) key 不要使用随机数(随机数在下一次render时,会重新生成一个数字,失去优化的意义);
(3) 使用index作为key,对性能时没有优化的;

三.组件嵌套的render调用

React中,使用setState修改数据后,就会重新的调用组件的render函数, 在多个组件嵌套的情况下,父组件(APP)中的数据修改并不影响子组件时,所有子组件也会重新调用render函数重新渲染,性能必然是很低的;
在这里插入图片描述

如何控制render方法是否被调用?

一.针对类组件

(1) shouldComponentUpdate() 生命周期函数(SCU);

1. 该方法参数:

  • 参数一: nextProps 修改之后,最新的props属性
  • 参数二: nextState 修改之后,最新的state属性

2. 该方法返回值是一个Boolean类型:

  • 返回true, 会调用render方法;
  • 返回false, 不会调用render方法;
  • 默认返回的是true,也就是只要state发生改变就会调用render;
    在这里插入图片描述

(2) PureComponent

如果所有的类组件,我们都需要手动来实现SCU,会给开发者增加非常多的工作量;

SCU使用的目的是什么?props或state中的数据是否发生了变化,来决定SCU返回true或false,最终决定是否更新当前的类组件;
事实上,react已经考虑到这一点,所以react已经帮我们实现好了,如何实现?
在这里插入图片描述
在这里插入图片描述
shallowEqual方法: 这个方法中,调用 !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState),这个shallowEqual就是进行浅层比较:在这里插入图片描述

如何使用?
将Component 替换成 PureComponent来创建类组件:
在这里插入图片描述

二.针对函数式组件

(1) 高阶组件memo
如何实现?在这里插入图片描述
如何使用?
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值