高级前端面试题(react + 原生js + es6)

export function scheduleUpdateOnFiber(
  fiber: Fiber,
  lane: Lane,
  eventTime: number,
) {
  if (lane === SyncLane) {
    // legacy或blocking模式
    if (
      (executionContext & LegacyUnbatchedContext) !== NoContext &&
      (executionContext & (RenderContext | CommitContext)) === NoContext
    ) {
      performSyncWorkOnRoot(root);
    } else {
      ensureRootIsScheduled(root, eventTime); // 注册回调任务
      if (executionContext === NoContext) {
        flushSyncCallbackQueue(); // 取消schedule调度 ,主动刷新回调队列,
      }
    }
  } else {
    // concurrent模式
    ensureRootIsScheduled(root, eventTime);
  }
}

lane === SyncLane也就是 legacy 或 blocking 模式中, 注册完回调任务之后(ensureRootIsScheduled(root, eventTime)), 如果执行上下文为空, 会取消 schedule 调度, 主动刷新回调队列flushSyncCallbackQueue().

这里包含了一个热点问题(setState到底是同步还是异步)的标准答案:

  • 如果逻辑进入flushSyncCallbackQueue(executionContext === NoContext), 则会主动取消调度, 并刷新回调, 立即进入fiber树构造过程. 当执行setState下一行代码时, fiber树已经重新渲染了, 故setState体现为同步.
  • 正常情况下, 不会取消schedule调度. 由于schedule调度是通过MessageChannel触发(宏任务), 故体现为异步.

React hooks相关:
       hook本质是将直接修改组件的state,改成了一个消息队列,通过useState中的set方法将修改事件推到队列中,react会进行合并和修改,然后自动触发setState。       
        useEffect在使用时候需要注意不能在外部使用判断,因为如果有判断的话,会导致react无法找到它而引发报错。第一个参数是回调函数,当不传递第二个参数的时候,每次render后都会执行,传递空数组的话,生命周期和componentDidMount一致,只会在组件挂载后执行一次,传递相关变量,那么会在第一次挂载和每次变量变化时执行。回调函数返回一个函数的话,这个函数对应的是componentWillUnmount钩子。
        useMemo(),缓存计算函数的结果,只有当第二个参数关心的变量发生变化时候才会再次执行计算,因为每次render都会让整个函数重新运行,如果不进行useMemo()缓存结果的话,那么每次render都会进行运算,会造成性能上的浪费。
     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值