React面试

React 面试

React 性能优化

  1. PureComponent, shouldComponentUpdate, memo, useMemo, useCallback 进行优化

  2. react-redux, useSelector, 尽量不要在 selector 里面组装结果,需要组装可以传入 equal 函数优化,或者使用 reselect 库

  3. useState 惰性初始化

  4. 对于经常需要重新渲染的组件,我们可以提取出子组件并用 memo 优化

useRef 使用场景

  1. 访问 dom 或 class 组件

  2. 通过 ref 访问最新的 state/props,而不需要将 state/props 作为 useEffect,useMemo 等的依赖

  3. 用来存储初始化时的 props,不再关注后续 props 变化

  4. 在 setTimeout 里面使用,避免闭包陷阱

组件封装思考

  • 提供哪些 props,重要:考虑哪些 props 只做初始化【defaultValue】,后续变化无效。 受控组件,非受控组件

  • 函数组件考虑 ref 转发,通过 ref 向外界传递哪些值或函数

  • 优先封装成函数,或者 hook,与 UI 解耦,更易复用

虚拟 DOM 是什么?

  • 真实 DOM 的抽象,js 对象(element tree,fiber tree)

为什么需要虚拟 DOM?/ 讲讲虚拟 DOM

  1. React 理念是数据驱动视图,虚拟 DOM 是视图(真实 DOM)的抽象,我们只需要修改数据生成新的虚拟 DOM, 再通过 dom diff,便能高效的更新视图

  2. 如果没有虚拟 DOM,某个组件更新,组件代表的真实 DOM 及子节点可能都需要重新生成

DOM diff 算法

  • 不同类型的元素,我们认为它的子节点也是不同的,直接替换这个节点

  • 相同类型的 dom,我们根据需要更新 dom 属性

  • 相同类型的 react 组件,我们根据需要更新 props,执行 render 方法,在 children 上重复这样的操作

  • 对于列表,如果 key 不同,认为不是相同节点,key 相同,再比较其他属性或 props 【列表 diff 有比较复杂的算法】

React 和 Vue

  • 相同: 1. 组件化 2.VDom dom-diff 3.数据驱动视图,都是改变数据来改变视图

  • 不同: 1. jsx vs 模版语法(vue-jsx 语法没用过) 2. 数据驱动视图的原理不太一样,vue 依赖收集和 dom-diff,react 完全依靠 dom-diff,当然 react 提供了一些优化手段(memo 等) 3. 使用体验,react 由于 jsx 语法,和写原生 js 差不多,能利用函数式编程的优势:函数就是组件,render-props,高级组件等都是函数作为一等公民的优势。

render 和 commit 阶段

  1. 渲染阶段:可以中断重新执行,所以其中的生命周期可能多次执行。从根节点开始遍历 Fiber Node,并且构建 WorkInProgress Tree,通过 Diff 算法计算所有更新工作,生成 EffectList

  2. 提交阶段:根据 EffectList 更新 DOM

tips

  • React 内部使用 createTextNode 创建文本节点,减少了 xss。对于 a 标签 href 的 xss 目前仅仅给出警告。

  • 每次重新渲染都会重新创建 Element,但是 FiberNode 不会,FiberNode 只会使用对应的 Element 中的数据来更新自己必要的属性

  • React.lazy 语法,可以实现组件的懒加载,通常基于路由懒加载。不能用于服务端渲染(服务端请用 Loadable),需要在外层包裹 Suspense,加载失败会报错。

  • React.lazy 目前只支持默认导出

  • Context 的值改变,所有用到 context 的值的地方都会重新渲染(不受 React.Memo 和 shouldComponentUpdate 的约束)。

  • Context 不能代替 redux,context 对象引用改变,所有用到 context 的组件会重新渲染;context 对象引用不改变(仅仅内部属性改变),组件不会重新渲染。

  • static getDerivedStateFromError: 处于 render 阶段,可能执行多次,不适合再此处发送错误日志等副作用操作!!!

  • componentDidCatch:处于 commit 阶段,适合做副作用操作,如发送错误日志!!!

  • renderProps:接受一个函数,返回 react element,可以将内部 state 通过函数参数共享出去。【向外部共享内部 state】

  • 惰性初始 state, 如果初始化 state 花费过高,可以传函数给 useState, 函数只在初始化渲染调用。

render 和 commit 阶段生命周期

  1. render 阶段会执行以下的生命周期钩子:

  • [UNSAFE_]componentWillMount(弃用)

  • [UNSAFE_]componentWillReceiveProps(弃用)

  • static getDerivedStateFromProps

  • static getDerivedStateFromError

  • shouldComponentUpdate

  • [UNSAFE_]componentWillUpdate(弃用)

  • render

  1. Commit 阶段会执行如下生命周期方法:

  • getSnapshotBeforeUpdate

  • componentDidMount

  • componentDidUpdate

  • componentWillUnmount

  • componentDidCatch

最后更新于