关于javascript:你应该理解的react知识点

45次阅读

共计 3528 个字符,预计需要花费 9 分钟才能阅读完成。

前言

最近在筹备面试。温习了一些 react 的知识点,特此总结。

开始

React 生命周期

react 16 以前的生命周期是这样的

组件在首次渲染时会被实例化,而后调用实例下面的 componentWillMount,render 和 componentDidMount 函数。组件在更新渲染时能够调用 componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render 和 componentDidUpdate 函数。组件在卸载时能够调用 componentWillUnmount 函数。

借图:

从 React v16.3 开始,React 倡议应用 getDerivedStateFromPropsgetSnapshotBeforeUpdate两个生命周期函数代替 componentWillMountcomponentWillReceivePropscomponentWillUpdate 三个生命周期函数。这里须要留神的是 新增的两个生命周期 函数和原有的三个生命周期函数必须离开应用,不能混合应用

目前的生命周期(借图):

componentWillMount 存在的问题

有人认为在 componentWillMount 中能够提前进行异步申请, 防止白屏。然而 react 在调用 render 渲染页面的时候,render 并不会期待异步申请完结,再获取数据渲染。这么写是有潜在隐患的。

而在 react fiber 之后 可能在一次渲染中屡次调用。起因是:react fiber 技术应用增量渲染来解决掉帧的问题,通过 requestIdleCallback 调度执行每个工作单元,能够中断和复原,生命周期一旦中断,复原之后会从新跑一次之前的生命周期

新的生命周期

static getDerivedStateFromProps

  • 触发工夫(v16.4 修改):组件每次被 rerender 的时候,包含在组件构建之后(render 之前最初执行),每次获取新的 props 或 state 之后。在 v16.3 版本时,组件 state 的更新不会触发该生命周期
  • 每次接管新的 props 之后都会返回一个对象作为新的 state,返回 null 则阐明不须要更新 state
  • 配合 componentDidUpdate,能够笼罩 componentWillReceiveProps 的所有用法

getSnapshotBeforeUpdate

  • 触发工夫: update 产生的时候,在 render 之后,在组件 dom 渲染之前。
  • 返回一个值,作为 componentDidUpdate 的第三个参数。
  • 配合 componentDidUpdate, 能够笼罩 componentWillUpdate 的所有用法。

React Fiber

因为 React 渲染 / 更新过程一旦开始无奈中断,继续占用主线程,主线程忙于执行 JS,得空他顾(布局、动画),造成掉帧、提早响应(甚至无响应)等不佳体验。fiber 应运而生。

Fiber 是对 react reconciler(和谐)外围算法的重构。要害个性如下:

  • 增量渲染(把渲染工作拆分成块,匀到多帧)
  • 更新时可能暂停,终止,复用渲染工作
  • 给不同类型的更新赋予优先级
  • 并发方面新的根底能力

增量渲染用来解决掉帧的问题,渲染工作拆分之后,每次只做一小段,做完一段就把工夫控制权交还给主线程,而不像之前长时间占用。

Fiber tree

  • Fiber 之前的 reconciler(被称为 Stack reconciler)自顶向下的递归 mount/update,无奈中断(继续占用主线程),这样主线程上的布局、动画等周期性工作以及交互响应就无奈立刻失去解决,影响体验。
  • Fiber 解决这个问题的思路是把渲染 / 更新过程(递归 diff)拆分成一系列小工作,每次查看树上的一小部分,做完看是否还有工夫持续下一个工作,有的话持续,没有的话把本人挂起,主线程不忙的时候再持续。

fiber 树其实是一个单链表构造,child 指向第一个子节点,return 指向父节点,sibling 指向下个兄弟节点。构造如下:

// fiber tree 节点构造
{
    stateNode,
    child,
    return,
    sibling,
    ...
}

Fiber reconciler

reconcile 过程分为 2 个阶段:

1.(可中断)render/reconciliation 通过结构 workInProgress tree 得出 change

2.(不可中断)commit 利用这些 DOM change(更新 DOM 树、调用组件生命周期函数以及更新 ref 等外部状态)

构建 workInProgress tree 的过程就是 diff 的过程,通过 requestIdleCallback 来调度执行一组工作,每实现一个工作后回来看看有没有插队的(更紧急的),每实现一组工作,把工夫控制权交还给主线程,直到下一次 requestIdleCallback 回调再持续构建 workInProgress tree

生命周期也被分成了两个阶段:

// 第 1 阶段 render/reconciliation
componentWillMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate

// 第 2 阶段 commit
componentDidMount
componentDidUpdate
componentWillUnmount

第 1 阶段的生命周期函数可能会被屡次调用,默认以 low 优先级执行,被高优先级工作打断的话,稍后从新执行。

fiber tree 与 workInProgress tree

双缓冲技术:指的是 workInProgress tree 结构结束,失去的就是新的 fiber tree,而后把 current 指针指向 workInProgress tree,因为 fiber 与 workInProgress 相互持有援用,旧 fiber 就作为新 fiber 更新的预留空间,达到复用 fiber 实例的目标。

每个 fiber 上都有个 alternate 属性,也指向一个 fiber,创立 workInProgress 节点时优先取 alternate,没有的话就创立一个

let workInProgress = current.alternate;
if (workInProgress === null) {
  //...
  workInProgress.alternate = current;
  current.alternate = workInProgress;
} else {
  // We already have an alternate.
  // Reset the effect tag.
  workInProgress.effectTag = NoEffect;

  // The effect list is no longer valid.
  workInProgress.nextEffect = null;
  workInProgress.firstEffect = null;
  workInProgress.lastEffect = null;
}

这么做的益处:

  • 可能复用外部对象(fiber)
  • 节俭内存调配、GC 的工夫开销

fiber 中断 复原

中断:查看以后正在解决的工作单元,保留以后成绩(firstEffect, lastEffect),批改 tag 标记一下,迅速收尾并再开一个 requestIdleCallback,下次有机会再做

断点复原:下次再解决到该工作单元时,看 tag 是被打断的工作,接着做未实现的局部或者重做

P.S. 无论是工夫用尽“天然”中断,还是被高优工作粗犷打断,对中断机制来说都一样。

React setState

在代码中调用 setState 函数之后,React 会将传入的参数对象与组件以后的状态合并,而后触发所谓的和谐过程(Reconciliation)。通过和谐过程,React 会以绝对高效的形式依据新的状态构建 React 元素树并且着手从新渲染整个 UI 界面。在 React 失去元素树之后,React 会主动计算出新的树与老树的节点差别,而后依据差别对界面进行最小化重渲染。在差别计算算法中,React 可能绝对准确地晓得哪些地位产生了扭转以及应该如何扭转,这就保障了按需更新,而不是全副从新渲染。

setState 调用时有时是同步的(settimeout, 自定义 dom 事件),有时是异步的(一般调用)

React 事件机制

React 事件是通过事件代理,在最外层的 document 上对事件进行对立散发,并没有绑定在实在的 Dom 节点上。
而且 react 外部对原生的 Event 对象进行了包裹解决。具备与浏览器原生事件雷同的接口,包含 stopPropagation()preventDefault()

正文完
 0