跳到主要内容

基础

参考 前端面试题之 React 篇

事件机制

参考 React17 事件机制

React 将所有 dom 的事件都委托到一个节点上,React 16 为 document,React 17 为 根 DOM 容器。

合成事件 SyntheticEvent 是 React 事件系统对于原生事件跨浏览器包装器。它除了兼容所有浏览器外,它还拥有和浏览器原生事件相同的接口,包括 stopPropagation() 和 preventDefault()

react_17_delegation

  • 将事件都代理到了根节点上,减少了事件监听器的创建,节省了内存
  • 磨平浏览器差异,开发者无需兼容多种浏览器写法,如想阻止事件传播只需写 event.stopPropagation()

React Fiber

React Fiber 为了解决 stack reconciler 无法中断,导致渲染线程挂起的问题。Fiber 把一个渲染任务分解为多个渲染任务,在空闲时间里去执行任务,可以让出控制权执行其他任务,实现更流畅的用户体验

为什么 useState 的返回值要使用数组而不是对象

数组解构后可以对数组元素进行重命名,而对象解构后需要使用别名

React Hook 的限制

  • 不要在循环、条件或嵌套函数中调用 Hook
  • 在 React 的函数组件中调用 Hook

因为 Hooks 的设计是基于链表实现,在调用时按顺序加入链表中,如果使用循环、条件或嵌套函数很有可能导致链表取值错位,执行错误的 Hook

useEffect 与 useLayoutEffect 的区别

useEffect 在 React 的渲染过程中是被异步调用的,且在 dom 更新后;而 useLayoutEffect 会在所有的 DOM 更新前同步调用,主要用于处理 DOM 操作、调整样式、避免页面闪烁等问题

useTransition

在 concurrency 模式下,useTransition 可以将某些更新标记为可中断的非紧急的

对虚拟 DOM 的理解

  • 对虚拟 DOM 将 DOM 抽象成 JS 对象,配合不同渲染工具,使跨平台渲染成为可能。
  • 通过事务处理机制,将多次 DOM 修改的结果一次性的更新到页面上,从而有效的减少页面渲染的次数,减少修改 DOM 的重绘重排次数,提高渲染性能

setState

在代码中调用 setState 函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发调和过程(Reconciliation)

如果在短时间内频繁 setState。React 会将 state 的改变压入栈中,在合适的时机,批量更新 state 和视图

setState 是同步还是异步的

react 18 以前,通过 isBatchingUpdates 来判断 setState 是先存进 state 队列还是直接更新,如果值为 true 则执行异步操作,为 false 则直接更新

异步: 在 React 可以控制的地方,就为 true,比如在 React 生命周期事件和合成事件中,都会走合并操作,延迟更新的策略 同步: 在 React 无法控制的地方,比如原生事件,具体就是在 addEventListener 、setTimeout、setInterval 等事件中,就只能同步更新。

react 18 以后,setState 都为异步,可以使用 flushSync 方法,使之变为同步

React 中 setState 的第二个参数作用是什么

是一个回调函数,在组件重新渲染后执行,可以拿到更新后的 state。等价于在 componentDidUpdate 生命周期内执行

React 中怎么检验 props

import PropTypes from 'prop-types'

class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>
}
}

Greeting.propTypes = {
name: PropTypes.string,
}
js

React-Router 的实现原理

基于 history 库来实现上述不同客服端路由

hash 路由: 监听 hashchange 事件,通过 location.hash=xxx 改变 hash 值

H5 history 路由: 通过 history.pushState 和 resplaceState 改变路由,通过自定义事件触发实现