2025前端高频最新面筋| React 篇

1,486 阅读9分钟

2025最新前端高频面筋| Vue篇

# 2025年从 SSR\SSG\ISR 到Nextjs 常见面题

2025最新面筋| 408篇

hello,jym,大家好。我是你们的ys 指风不买醉,关注我——学技术不迷路 😊

迷茫之中还是写写文章,沉淀一下。如果你处于迷茫之中,不如来看看这篇总结分析是否到位。😋 黎明前的黑暗,不可以倒在“最后一公里”的上坡路的地方。

📘 目录结构图

  1. Vue 与 React 的核心区别
  2. 水合(Hydration)与合成事件(Synthetic Events)
  3. React Fiber 架构详解
  4. 中间层解耦:前后端通信桥梁
  5. React Hooks 与工具函数(Utils)的区别
  6. React 18 的新特性
  7. useCallback 与 useMemo 的使用场景
  8. 受控组件与非受控组件的区别
  9. React 的状态管理方式
  10. Redux 与 useState/useEffect 的差异
  11. 事件总线(EventBus)的实现与应用

Vue 和 React 的区别

从多个维度展开:

设计理念

  • Vue:作为渐进式框架,Vue 专注于业务逻辑,通过指令和组件来扩展功能。其核心是响应式系统,利用数据驱动视图的更新。Vue 能够自动跟踪依赖,Vue 3 使用 Proxy 替代了 Object.defineProperty,性能更优。
  • React:专注于组件化开发,通常需要结合其他库(如 Zustand、Redux 等)来构建完整应用。状态更新需要显式调用 useState,依赖手动操作。

代码层面

  • Vue:采用单文件组件(.vue),将模板、样式和逻辑封装在一个文件中,提高了代码的可读性和可维护性。
  • React:使用 Hooks(如 useState、useEffect)管理状态和副作用,强调逻辑复用和组合。类组件是传统方式,逐渐被 Hooks 替代,依赖生命周期方法。

数据流和状态管理

  • Vue:使用 v-model 实现数据双向绑定,简化了表单处理。底层是单向数据流加事件监听的语法糖。
  • React:使用 useState 和 useEffect 实现数据流和状态管理,依赖收集,数据变化时视图更新。

水合(Hydration)与合成事件(Synthetic Events)

水合(Hydration)

水合是指服务器生成的静态 HTML 与客户端 JavaScript 事件处理程序和状态结合的过程。服务器生成的 HTML 包含了事件处理程序和状态,客户端 JavaScript 负责将这些信息与 DOM 进行关联,使得用户交互能够正常工作。

React 实现方式:

  • React 18 以前:ReactDOM.hydrate(element, container)
  • React 18 以后:hydrateRoot(container, element)

合成事件机制(Synthetic Events)

合成事件是 React 特有的事件处理系统:

  • 定义:React 将原生 DOM 事件包装成合成事件对象,统一绑定到根节点(document)。

  • 工作原理

    • 事件委托:所有事件都委托到根节点,而不是直接绑定到 DOM 元素。
    • 事件池:重用事件对象,减少内存消耗。
    • 事件分发:根据事件冒泡路径,找到对应组件并执行其事件处理函数。

主要区别

  • 目的不同

    • 水合:解决 SSR 与客户端渲染的衔接问题。
    • 合成事件:解决跨浏览器兼容性和性能优化问题。
  • 作用范围

    • 水合:整个应用的生命周期中只发生一次。
    • 合成事件:贯穿应用的整个生命周期。
  • 技术领域

    • 水合:服务端渲染与客户端渲染的桥梁。
    • 合成事件:前端事件处理系统。

Fiber 机制

React 的 Fiber 架构引入了增量渲染、优先级调度和双缓存树的概念。

  • 增量渲染:将渲染任务分割成多个小任务,配合优先级调度机制,让高优先级的任务(如用户输入)可以中断低优先级的任务(如大列表渲染),提升用户体验。

  • 双缓存树设计:在内存中同时存在两棵树:当前页面对应的树(current 树)和正在构建的树(workInProgress 树)。这种机制让 React 可以在后台准备新的树,完成后再一次性替换到屏幕上,避免中间状态造成的视觉问题。

  • 更新过程分为两个阶段

    • Render 阶段:构建 Fiber 树和标记副作用,这个阶段是可以被中断的。
    • Commit 阶段:将变更应用到 DOM 上,这个阶段必须一次性完成,不能中断。

中间层解耦

中间层是介于前端和后端之间的一层,用于处理前端和后端之间的通信和数据传输。

  • 功能

    • 处理接口的新旧版本兼容。
    • 支持多端数据。
    • 性能优化,如减少请求次数、缓存处理。
    • 错误和日志记录,便于问题追踪和分析。

React Hooks 与 Utils 的区别

  • React Hooks:Hooks 是 React 16.8 新增的特性,允许在函数组件中使用状态和其他 React 特性,打破了函数组件只能渲染 UI,不能使用状态和生命周期的限制。通常以 use 开头,如 useStateuseEffectuseContext 等。

    • 例如,useContext 用于组件树传递上下文(context),避免通过逐层传递 props 的麻烦。
  • Utils:指的是开发者自己编写的一些工具函数,用于解决特定问题,实现某些逻辑,减少重复代码。这些函数不依赖于 React 的生命周期,可以在任何 JavaScript 环境中使用。

React 18 新特性

React 18 引入了多项新特性,旨在提升性能和开发体验:

  • 异步渲染:引入并发渲染(Concurrent Rendering),允许 React 根据任务优先级中断和恢复渲染,提高应用响应速度。
  • Canvas 渲染功能:提供了通过 Canvas 渲染组件的能力,适用于需要高性能图形渲染的场景。
  • Suspense for Server:增强了服务器端渲染(SSR)对异步组件加载的支持,使得服务器渲染可以更好地处理异步数据加载。
  • 重写 Fiber 架构:提升了性能,支持渲染任务的中断和恢复,优化了用户体验。

useCallback 与 useMemo

  • useCallback:用于缓存函数,避免每次渲染都创建新函数,从而减少函数创建成本,提升性能,减少子组件不必要的渲染。使用方式:useCallback(fn, deps),当依赖项 deps 改变时,重新创建函数。

    • 使用场景

      • 当函数作为 props 传递给子组件时,避免子组件因函数引用变化而重新渲染。
      • 优化事件处理函数,避免不必要的函数重新创建。
    • 注意事项useCallback 本身存在开销,需要维护一个缓存,并且每次渲染都要检查依赖项是否变化。如果子组件渲染不是性能瓶颈,或函数依赖变化少,使用 useCallback 可能会增加不必要的开销,增加代码复杂性和维护成本。

  • useMemo:用于缓存计算结果,避免每次渲染都进行重复计算,提升性能。使用方式:useMemo(fn, deps),当依赖项 deps 改变时,重新计算值。

    • 使用场景

      • 当组件中存在复杂的计算逻辑(如数组排序、数据处理等),且这些计算依赖于某些变量时,可以使用 useMemo 缓存结果。
      • 当计算结果作为子组件的 props 时,useMemo 可以防止子组件因父组件的重新渲染而进行不必要的更新。

受控与非受控组件

  • 受控组件:通过 state 控制组件状态,通过 onChange 事件更新 state,通过 state 渲染组件。可以通过代码修改表单的 value,适合需要表单校验、动态控制等场景。
  • 非受控组件:通过 ref 获取 DOM 节点,直接操作 DOM 节点。只有用户能够改变 value,不能通过代码修改 value;但可以设置 defaultValue 初始值,通过 ref 获取 DOM 节点,操作 DOM 节点。适合文件上传、简单表单等场景。

一般来说,只要用户输入,不手动修改表单值,使用非受控组件即可。

受控组件与非受控组件的性能差异

  • 受控组件:每次用户输入都会触发状态更新和组件渲染,可能导致性能开销。
  • 非受控组件:减少了不必要的状态更新和渲染,性能更优,但不适合复杂的表单验证场景。

React 如何进行状态管理?为什么需要状态管理?

  • 内置方案

    • useState:适用于简单状态管理。
    • useReducer:适用于更复杂的状态逻辑。
    • useContext(Context API):用于跨组件共享状态。掘金
  • 第三方方案

    • Redux:全局状态管理,适用于大型应用。
    • Zustand:轻量级状态管理库,使用简单,性能优越。知乎+3掘金+3Reddit+3
  • 状态管理的作用

    • 实现组件通信:父子组件通过 props,自定义事件;兄弟组件通过状态提升或事件总线;跨层组件通过 Context API。
    • 状态共享:统一数据源,减少重复请求。
    • 处理复杂逻辑:通过状态机制管理,实现高效共享和同步更新。

示例代码:

const UserContext = React.createContext();

// 提供状态
function App() {
  return (
    <UserContext.Provider value={{ name: 'zhangsan' }}>
      <Child />
    </UserContext.Provider>
  );
}

// 消费状态
function Child() {
  const { name } = useContext(UserContext);
  return <div>{name}</div>;
}

Redux 与 useState/useEffect 的区别

  • Redux

    • 全局状态管理,适用于大型应用。
    • 支持状态历史跟踪。
    • 通过中间件(如 redux-thunk)处理异步操作。
    • 支持状态持久化(如 redux-persist)。
  • Zustand

    • 轻量级,性能优越。
    • 使用 create 创建状态管理器(store),定义状态和修改方法。
    • 通过 useStore hook 在组件中访问和更新状态。
  • 事件总线(EventBus)

    • 基于发布-订阅通信机制,允许通过一个中央事件中心存储事件和对应回调函数。
    • on 订阅事件,emit 发布(触发)事件,off 取消订阅(解绑)。
    • 注意:订阅和发布分离,订阅者不知道发布者存在,订阅者也不知道发布者发布什么事件,可能导致维护困难。

实现方式:父组件通过调用事件总线的 emit 方法触发事件,并传递数据。子组件通过调用事件总线的 on 方法订阅事件,并注册回调函数来响应事件。子组件在卸载时需要调用 off 方法解绑事件,以避免内存泄漏。