React 源码揭秘 | bailout策略&Memo

前面的文章介绍了React 更新 render + commit的完整流程,下面来说一下一些优化策略。

bailout 即 熔断策略,即在BeginWork阶段,如果递到某个节点的子树, 如果该节点的子树已经不需要更新了,即和current保持一致了,那么可以直接熔断(bailout)当前Beginwork过程,复用current的子树即可。

如何确定子树不用更新了?

这个取决于四要素,即current节点和新Fiber节点的

  1.  Props相等
  2.  type相等代码
  3.  当前Fiber节点不包含当然renderedLane更新
  4.  如果当前节点是Context节点,需要相等 (这个先不用管)

我们主要看前三条,如何判断这三条是否满足bailout条件

Props & type

props和bailout判断条件如下,代码在react-reonciler/beginwork.ts -> beginWork函数

  didReceiveUpdate = false;
  const current = wip.alternate;

  if (current !== null) {
    /** 更新模式下 才检查是否bailout */
    /** 检查props和type */
    const prevProps = current.memorizedProps;
    const wipProps = wip.pendingProps;
    /**
     * 注意 bailout的props直接检查对象地址是否相等
     * 如果父节点存在更新 那么子节点无法bailout 需要通过childReconcile创建
     * 那么子节点的 props一定和current.props不一样 因为createElement中传入的对象也不是相同地址 比如
     * current createElement('div',{a:100}) -父节点不同,导致reconcilechild-> createElement('div',{a:100})
     * 注意 虽然都是{a:100} 但是两个对象来源于两次render 其对象地址不同,这也就导致如果父节点没能bailout 子节点也无法bailout 就必须使用memo来shallowEqual
     */
    if (prevProps !== wipProps || current.type !== wip.type) {
      // 检查不通过
      didReceiveUpdate = true;
    } else {
      ... ... ...
    }
  }

可以看到,Props和type的判等简单的通过 "!==" 完成

beginWork维护一个全局变量didReceiveUpdate: boolean 并且将其封装成一个函数导出

/** 是否收到更新 默认为false 即没有更新 开启bailout */
let didReceiveUpdate: boolean = false;

/** 标记当前wip存在更新 不能bailout
 * 导出接口 方便其他模块 (hooks) 使用 */
export function markWipReceiveUpdate() {
  didReceiveUpdate = true;
}

markWipReceiveUpdate可以方便的在其他模块内导入,并且修改didReceiveUpdate的值

判断Update

如果Props和Type都没有变化,接下来会判断当前节点是否存在当前renderLane对应的更新。

    if (prevProps !== wipProps || current.type !== wip.type) {
      // 检查不通过
      didReceiveUpdate = true;
    } el
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值