banner
NEWS LETTER

面试备忘2

Scroll down

1. Vue 和 React 的主要区别

对比维度 Vue React
核心设计思想 渐进式框架,主打 MVVM 双向绑定,官方 API 开箱即用,上手门槛低 专注视图层的 UI 库,推崇单向数据流与函数式编程,核心理念为 UI = f(state)
数据绑定方式 双向数据绑定(v-model 语法糖),视图修改自动同步到数据 严格单向数据流,视图变更需通过事件回调手动更新状态
响应式原理 Vue2 基于 Object.defineProperty,Vue3 基于 Proxy 劫持数据,精准追踪依赖 基于不可变数据,通过 setState / useState 手动触发重渲染,靠引用变化判断更新
模板写法 采用 <template> 模板语法,贴近原生 HTML,学习成本低 采用 JSX 语法,完全基于 JavaScript 编写 UI,灵活度更高,与 JS 生态融合更好
Diff 算法 采用双端对比的虚拟 DOM Diff 算法 React 16 后引入Fiber 架构,以链表结构实现可中断、可优先级调度的 Diff 过程
生态与灵活性 官方提供 Router、Pinia 等完整全家桶,方案统一规范 生态开放灵活,状态管理、路由等均为社区方案,适合复杂大型项目定制化开发

2. JS 的事件循环机制

JavaScript 是单线程语言,事件循环(Event Loop)是其处理异步任务的核心机制,用于保证代码执行不阻塞,核心围绕调用栈任务队列运行。

核心规则

  1. 同步代码直接进入调用栈依次执行,执行完毕后栈被清空。
  2. 异步代码会被挂起,等到触发时机(定时器到期、网络请求返回等),对应的回调函数会被推入任务队列。
  3. 当调用栈为空时,先清空所有微任务,再取出一个宏任务执行,如此循环往复。

任务分类

  • 宏任务:整体 script 代码、setTimeoutsetInterval、I/O 操作、UI 渲染
  • 微任务Promise.then/catch/finallyqueueMicrotaskMutationObserver

完整执行顺序

  1. 执行全局同步代码(属于第一个宏任务)
  2. 同步代码执行完毕,调用栈清空
  3. 依次执行当前所有微任务,直到微任务队列清空
  4. 浏览器执行 UI 渲染(可选步骤)
  5. 取出下一个宏任务执行,回到步骤 2 循环

3. React 局部状态管理方式

局部状态指仅在单个组件或小范围组件树内生效的状态,不依赖全局状态库,常见方式如下:

  • 组件基础内部状态

    • 类组件:this.state + this.setState()
    • 函数组件:useState,最常用的局部状态 Hook,适合简单单一状态
  • 复杂局部状态

    • useReducer:适合状态逻辑复杂、多个子状态互相关联、下一个状态依赖上一个状态的场景,通过 reducer 函数统一管理状态更新逻辑
  • 非渲染型局部状态

    • useRef:存储不需要触发组件重渲染的变量(如定时器 ID、DOM 引用、上一次的值等),值变更不会引发重渲染
  • 组件树局部共享状态

    • 状态提升:将多个子组件的共享状态提升到最近的共同父组件,通过 props 向下传递,适合层级较浅的共享场景
    • Context API + useState/useReducer:在指定组件树范围内提供状态,避免 props 层层透传,属于局部范围的状态共享方案

4. React 性能优化手段

核心优化方向为减少不必要的重渲染降低渲染计算量,常见手段如下:

渲染层面优化

  • 类组件:使用 PureComponent 或自定义 shouldComponentUpdate,通过浅比较 props 和 state 跳过不必要的更新
  • 函数组件:用 React.memo 包裹组件,对 props 做浅比较,缓存组件渲染结果
  • 缓存计算与函数
    • useMemo:缓存复杂计算的结果,避免每次渲染都重新计算
    • useCallback:缓存函数引用,配合 React.memo 使用,避免子组件因函数引用变化而重渲染
  • 状态拆分:把不相关的状态拆分为独立的 state,避免单个状态变更引发全组件重渲染

结构与交互优化

  • 组件粒度拆分:将大组件拆分为职责单一的小组件,精准控制渲染范围
  • 正确使用 key:列表渲染时使用唯一稳定的 key,提升 Diff 算法效率,禁止用数组 index 作为 key
  • 长列表优化:使用 react-window / react-virtualized 实现虚拟滚动,只渲染可视区域节点
  • 代码分割:用 React.lazy + Suspense 实现路由/组件的按需懒加载,减少首屏包体积
  • React 18 并发优化:使用 useTransitionuseDeferredValue 区分紧急更新和非紧急更新,避免低优先级任务阻塞 UI 交互

编码习惯优化

  • 避免在组件渲染函数中直接创建内联对象、内联函数作为 props
  • 避免在渲染过程中执行副作用,统一放到 useEffect
  • 合理使用 useRef 存储频繁变更且不需要触发渲染的值

5. React 子组件方法暴露给父组件调用的方式

核心思路是通过 ref回调注册让父组件拿到子组件的方法引用,常用方案有三种:

  1. ref 直接获取(仅适用于类组件)
    类组件存在实例对象,父组件通过 createRef 创建 ref 并绑定到子组件上,即可通过 ref.current 直接调用子组件实例上的方法。

  2. forwardRef + useImperativeHandle(函数组件官方标准方案)
    函数组件没有实例,不能直接通过 ref 获取方法,需两步实现:

    • 子组件用 forwardRef 包裹,接收父组件传入的 ref
    • 子组件内部用 useImperativeHandle 自定义暴露给父组件的方法和属性
      该方案可控性强,是函数组件场景下的最推荐方案。
  3. props 回调注册法
    父组件通过 props 传递一个注册函数给子组件,子组件在挂载时(useEffect)将自身的方法作为参数传入该回调,父组件保存方法引用后即可调用。适合场景简单、不想使用 ref 的情况。

React Fiber 简单介绍

Fiber 是 React 16 推出的全新协调引擎(Reconciler),核心目标是解决旧版同步渲染阻塞主线程的卡顿问题,让 React 的更新过程变得可中断、可恢复、可按优先级调度

1. 诞生背景

React 15 及更早版本采用「Stack Reconciler」,通过递归遍历虚拟 DOM 树做 Diff 比对,整个更新过程是同步且不可中断的。一旦组件树庞大、更新计算耗时过长,就会阻塞浏览器主线程,导致用户输入、动画、页面滚动出现掉帧和卡顿。

2. 核心设计与实现

  • 任务分片 + 链表结构
    将整个渲染更新任务拆分为一个个细小的「Fiber 工作单元」,每个 Fiber 节点对应一个组件,以链表形式组织(包含 child 子节点、sibling 兄弟节点、return 父节点三个指针),替代了原本的递归遍历。任务可以随时暂停,后续从中断点继续执行,不再依赖浏览器调用栈。

  • 时间片调度
    配合 Scheduler 调度器,在浏览器的空闲时间片内执行 Fiber 任务;时间片耗尽后立刻暂停工作,把主线程交还给浏览器处理用户交互、UI 渲染等高优先级操作,避免页面假死。

  • 双缓存机制
    同时维护两棵 Fiber 树:当前屏幕正在显示的 current 树,和后台正在计算更新的 workInProgress 树。所有更新计算完成后,才会一次性替换两棵树的引用,保证用户不会看到中间的不完整渲染状态。

  • 优先级调度
    给不同更新赋予不同优先级(比如用户点击/输入是高优先级,异步数据加载更新是低优先级),高优先级任务可以打断正在进行的低优先级任务,优先响应用户感知强的交互。

3. 核心价值

Fiber 把原本同步阻塞的渲染流程,改造为异步可调度的协作式任务系统,在不改变 React 开发体验的前提下,大幅提升了复杂大型应用的页面流畅度和交互响应性。

Redux 的核心作用

Redux 是一款可预测的 JavaScript 状态容器,是 React 生态中最主流的全局状态管理方案,核心用于集中管理应用的共享状态,规范状态更新流程,提升大型项目的可维护性。

1. 集中管理全局共享状态

解决 React 组件间跨层级通信、兄弟组件状态共享的痛点,避免 props 层层透传(Prop Drilling)问题。
将应用中通用的全局状态(如用户登录信息、主题配置、购物车数据、全局弹窗状态等)统一存储在唯一的 Store 中,项目内任意组件均可直接订阅、读取状态。

2. 规范状态更新,保证可预测性

遵循严格的单向数据流原则,状态更新必须遵循固定流程:
dispatch(action) → reducer 纯函数计算 → 返回新 state
禁止直接修改状态,所有状态变更都有迹可循;配合 Redux DevTools 可以回溯、复现每一次状态变化,大幅降低复杂业务的调试成本。

3. 解耦状态逻辑与 UI 组件

将业务状态逻辑、副作用逻辑从组件中抽离,统一放到 action、reducer、中间件中维护。
组件仅负责「订阅状态渲染UI」和「触发action更新状态」,职责更单一,在大型项目中更易拆分、测试与迭代。

4. 生态适配复杂业务场景

通过配套中间件扩展能力,覆盖复杂业务需求:

  • 异步处理:通过 redux-thunk / redux-saga 管理接口请求等异步副作用
  • 工程简化:官方推荐的 Redux Toolkit (RTK) 大幅减少样板代码,内置不可变更新、状态切片、数据缓存(RTK Query)等能力
  • 中间件扩展:支持日志、持久化、权限拦截等自定义扩展能力

支持我,让我有更多动力写出更好的文章

其他文章
目录导航 置顶
  1. 1. 1. Vue 和 React 的主要区别
  2. 2. 2. JS 的事件循环机制
    1. 2.1. 核心规则
    2. 2.2. 任务分类
    3. 2.3. 完整执行顺序
  3. 3. 3. React 局部状态管理方式
  4. 4. 4. React 性能优化手段
    1. 4.1. 渲染层面优化
    2. 4.2. 结构与交互优化
    3. 4.3. 编码习惯优化
  5. 5. 5. React 子组件方法暴露给父组件调用的方式
    1. 5.1. React Fiber 简单介绍
    2. 5.2. 1. 诞生背景
    3. 5.3. 2. 核心设计与实现
    4. 5.4. 3. 核心价值
  6. 6. Redux 的核心作用
    1. 6.1. 1. 集中管理全局共享状态
    2. 6.2. 2. 规范状态更新,保证可预测性
    3. 6.3. 3. 解耦状态逻辑与 UI 组件
    4. 6.4. 4. 生态适配复杂业务场景