know

react

高优先级知识点,需要熟练掌握。

  1. 18 道 react 面试
  1. react 原理

网址 (opens new window)

# 1. React Hooks 当中的 useEffect 是如何区分生命周期钩子的

useEffect 可以看成是 componentDidMount,componentDidUpdate 和 componentWillUnmount 三者的结合。

# 2. 为什么不能用数组下标来作为 react 组件中的 key?

  1. 在数组头部或中部插入或删除元素: 所有 key 对应的节点的值发生更改,进行重新渲染。造成性能损耗
  2. 而如果使用数组中唯一值来作为 key:不管是在何处插入或删除节点,其他 key 对应的节点的值未发生更改,只需插入或删除操作的数组节点。

# 3. React Fiber 是什么?(https://fe.ecool.fun/topic-answer/7830d575-2143-47c3-b938-2f9448a7465e?orderBy=updateTime&order=desc&tagId=13)

Fiber 的中文翻译叫纤程,与进程、线程同为程序执行过程,Fiber 就是比线程还要纤细的一个过程。纤程意在对渲染过程实现进行更加精细的控制。

  1. Fiber 把一个渲染任务分解为多个渲染任务,而不是一次性完成,把每一个分割得很细的任务视作一个"执行单元",React 就会检查现在还剩多少时间,如果没有时间就将控制权让出去,故任务会被分散到多个帧里面,中间可以返回至主进程控制执行其他任务,最终实现更流畅的用户体验。

  2. 即是实现了"增量渲染",实现了可中断与恢复,恢复后也可以复用之前的中间状态,并给不同的任务赋予不同的优先级,其中每个任务更新单元为 React Element 对应的 Fiber 节点。

3.1 链表树 3.2 双缓冲双缓冲 3.3 时间切片 3.4 优先级调度

# 4. React 有哪些性能优化的方法?

  1. 减少计算的量。 -> 对应到 React 中就是减少渲染的节点 或者 降低组件渲染的复杂度
  2. 利用缓存
  3. 精确重新计算的范围

# 5. 5.redux 就是一个实现上述集中管理的容器,遵循三大基本原则:

  1. 单一数据源
  2. state 是只读的
  3. 使用纯函数来执行修改

# 6. React 生命周期方法是什么?

React 组件的生命周期方法分为三个阶段:挂载、更新、卸载。

# 6.1. 挂载阶段

  • constructor:组件初始化
  • componentWillMount(已废弃):组件挂载前调用
  • componentDidMount:组件挂载后调用,适合进行 DOM 操作或数据请求

# 6.2. 更新阶段

  • componentWillReceiveProps(已废弃):父组件传递新的 props 时调用
  • shouldComponentUpdate:判断组件是否需要重新渲染
  • componentWillUpdate(已废弃):组件更新前调用
  • componentDidUpdate:组件更新后调用

# 6.3. 卸载阶段

  • componentWillUnmount:组件卸载前调用,适合清理定时器、事件监听等

注意:新版 React 推荐使用 componentDidMountshouldComponentUpdatecomponentDidUpdatecomponentWillUnmount,并用 Hooks 替代部分生命周期方法。

# 7. 说说 React render 方法的原理?在什么时候会被触发?

# 8. SetState 是同步还是异步的,setState 做了什么?

setState()函数通常被认为是异步的,这意味着调用 setState()时不会立刻改变 react 组件中 state 的值,setState 通过触发一次组件的更新来引发重汇,多次 setState 函数调用产生的效果会合并 调用 setState 时,React 会做的第一件事情是将传递给 setState 的对象合并到组件的当前状态。这将启动一个称为和解(reconciliation)的过程。和解(reconciliation)的最终目标是以最有效的方式,根据这个新的状态来更新 UI。 为此,React 将构建一个新的 React 元素树(您可以将其视为 UI 的对象表示)。 一旦有了这个树,为了弄清 UI 如何响应新的状态而改变,React 会将这个新树与上一个元素树相比较

# 9. 什么是 fiber,fiber 解决了什么问题?

React15 的 StackReconciler 方案由于递归不可中断问题,如果 Diff 时间过长(JS 计算时间),会造成页面 UI 的无响应(比如输入框)的表现,vdom 无法应用到 dom 中。 为了解决这个问题,React16 实现了新的基于 requestIdleCallback 的调度器(因为 requestIdleCallback 兼容性和稳定性问题,自己实现了 polyfill),通过任务优先级的思想,在高优先级任务进入的时候,中断 reconciler。 为了适配这种新的调度器,推出了 FiberReconciler,将原来的树形结构(vdom)转换成 Fiber 链表的形式(child/sibling/return),整个 Fiber 的遍历是基于循环而非递归,可以随时中断。

# 10. diff 原理

  1. 把树形结构按照层级分解,只比较同级元素。
  2. 列表结构的每个单元添加唯一的 key 属性,方便比较。
  3. React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
  4. 合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty 到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制.
  5. 选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。

# 11. 受控组件和非受控组件

受控组件:表单数据由 React 组件的 state 统一管理(React 掌控); 非受控组件:表单数据由 DOM 自身管理(原生 DOM 掌控),React 仅在需要时通过 ref 获取数据。

# 12. 为什么虚拟 dom 能提高性能

虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。 具体实现步骤如下: 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异

# 13. React 有哪几种创建组件方法

  1. React.createClass 传统方式
  2. ES6 class
  3. 无状态函数

# 14. react 的 keep-alive 如何做的

React Keep Alive 提供了 ,你必须把 放在 Provider 里面,并且每个 组件都必须拥有一个唯一的 key

# 15. props 和 state 的区别

props 是不可变的,state 是可变的 props 可以从父组件传递数据到子组件,而 state 是在组件内管理的状态,两者都是纯 JavaScript 对象

上次更新: