Blog
首页
文档
收藏
关于
  • 在线转换时间戳 (opens new window)
  • 在线压缩图片 (opens new window)
  • Float-Double转二进制 (opens new window)
  • 文件转Hex字符串 (opens new window)

HiuZing

🍑
首页
文档
收藏
关于
  • 在线转换时间戳 (opens new window)
  • 在线压缩图片 (opens new window)
  • Float-Double转二进制 (opens new window)
  • 文件转Hex字符串 (opens new window)
  • 前端面试题

  • JavaScript

  • Vue2

  • port

  • CSS

  • Node.js

  • JavaScript优化

  • uniapp

  • Mini Program

  • TypeScript

  • JavaScript 面向对象

  • UI组件

  • Plugin

  • Vue3

  • 性能优化

    • 网络优化
    • JS性能优化
    • Vue性能优化
    • React性能优化
      • 分维度整理
        • 渲染优化(React 层面)
        • 资源加载优化
        • 浏览器渲染层优化
        • 网络请求优化
      • 其他性能问题
        • React
        • React Native
        • App发布与Native方向
        • BLE
        • 部署
  • Axios

  • 状态管理

  • React

  • Mock

  • Icon

  • Template

  • 构建工具

  • 项目规范配置

  • Taro

  • SVG

  • React Native

  • Three.js

  • Flutter

  • 前端
  • 性能优化
HiuZing
2026-08-18
目录

React性能优化

# 分维度整理

# 渲染优化(React 层面)

  1. 减少不必要重渲染

◦ 组件:React.memo 纯组件浅对比 props;

◦ 函数:useCallback缓存回调传给子组件;

◦ 计算值:useMemo缓存复杂计算;

◦ 拆分组件,细粒度更新,避免顶层状态变更全树重渲染。

  1. 长列表优化

◦ 虚拟列表react-window / react-virtualized,只渲染可视区域DOM;

◦ 分页、懒加载,减少一次性渲染数据量。

  1. 副作用优化

◦ useEffect正确填写依赖,及时清理定时器、事件监听;

◦ 大量 DOM 操作放 useLayoutEffect,避免多次回流。

  1. 状态优化

◦ 拆分 useState,局部状态局部更新;

◦ 复杂状态用 useReducer,集中更新逻辑。

# 资源加载优化

  1. 静态资源:图片压缩、webp格式、懒加载、CDN;

  2. 代码分割:路由懒加载、动态 import,分包减小首屏包体积;

  3. 缓存策略:浏览器强缓存、协商缓存;

  4. 第三方库按需引入,移除冗余依赖。

# 浏览器渲染层优化

  1. 减少 DOM操作,批量修改DOM;

  2. 避免频繁回流重绘,使用 transform、opacity开启GPU加速;

  3. 防抖节流处理高频事件(scroll、resize、input)。

# 网络请求优化

  1. 请求合并、接口分页;

  2. 请求缓存 SWR/ React Query,重复请求拦截;

  3. 避免渲染中重复发请求。

# 其他性能问题

# React

  1. React 为什么会重新渲染?React 的更新机制是什么?

    答:React 组件重新渲染主要是由于组件自身 state 更新、父组件重新渲染导致 props 变化、Context 数据变化等原因触发。当 React 检测到组件需要更新时,会重新执行函数组件,生成新的 Virtual DOM,然后通过 Diff 算法比较新旧 Virtual DOM,最终只更新真实 DOM 中发生变化的部分。

    state 修改一定会触发 render 吗?

    答:不一定。如果调用 setState,但是新旧 state 值相同,React 会通过 Object.is 判断,如果值没有变化,可能会跳过重新渲染。

    props 变化如何判断?

    答:React 默认通过父组件重新渲染,然后重新比较传入组件的 props。如果 props 引用发生变化,React 会认为 props 更新。

    React.memo 为什么可以减少渲染?

    答:React.memo 会对组件的 props 进行浅比较,如果 props 没有变化,则复用之前的渲染结果,避免组件重新执行。

    useMemo 一定能优化性能吗?

    答:useMemo 本身也有缓存成本,并不是所有场景都适合使用。如果计算逻辑简单,使用 useMemo 反而增加比较成本。

  2. React.memo 的原理是什么?什么时候不适合使用?

    答:React.memo 本质是一个高阶组件,通过对比组件前后 props 是否变化决定是否重新渲染。如果 props 没变化,则跳过组件 render。

    React.memo 和 PureComponent 区别?

    答:两者作用类似,都是通过浅比较减少无效渲染。React.memo 用于函数组件;PureComponent 用于 class组件;React.memo 可以通过第二个参数自定义比较逻辑;

    为什么 memo 之后还是会更新?

    答:memo仅仅浅对比。props引用变化;state变化;context变化;父组件传入新的对象都会再更新。

    props 是对象怎么办?

    答:因为 memo 是浅比较,对象比较的是引用地址,所以如果对象每次重新创建,会导致重新渲染。可以使用 useMemo 固定对象引用,或者优化 props 结构。

    const user = useMemo(()=>({
    name
    }),[name])
    
    1
    2
    3
  3. useMemo 和 useCallback 的区别?

    答:useMemo 缓存的是计算结果;useCallback 缓存的是函数引用。

    两者解决什么问题?

    答:能带来性能优化,减少不必要的渲染

    是否所有函数都应该 useCallback?

    答:不是,多数用来作为组件的函数,减少重复渲染

    useMemo 缓存的数据什么时候释放?

    答:React 会在组件卸载时释放缓存;另外 React 也可能根据内部策略丢弃缓存,所以不能依赖 useMemo 做业务数据存储。

  4. React 为什么需要 key?

    答:key 是 React Diff 算法识别列表元素身份的重要依据。通过 key,React 可以判断哪些节点新增、删除、移动,从而提高列表更新效率。

    为什么不推荐 index 做 key?

    答:当列表发生插入、删除、排序时,index 会发生变化,导致 React 错误复用组件状态。

  5. Redux / Zustand 为什么可以做到跨组件通信?

    答:Redux/Zustand 本质维护一个独立于 React 组件树的全局 store,任何组件都可以订阅 store 数据,当数据变化时通知对应组件更新。

    Zustand 和 Context 区别?

    答:Zustand 使用订阅机制,组件只监听自己需要的数据,不像 Context value 改变会导致所有消费者重新渲染。

    为什么 Zustand 性能更好?

    答:

    Zustand 如何避免无效更新?

    答:通过 selector 精确订阅状态,只监听需要的数据,并且内部通过 Object.is 判断数据是否变化。

  6. 大型项目如何设计状态管理?

    答:以 项目为例,蓝牙状态、球队状态、脚环信息、脚环文件信息、用户管理

  7. 什么情况下使用 Context,什么情况下使用状态管理库?

    答:像主题颜色使用Context,脚环状态会使用状态管理库

  8. React Fiber 是什么?为什么需要 Fiber?

  9. React Diff 算法原理?

  10. Virtual DOM 一定比直接操作 DOM 快吗?

  11. 如何优化 React 首屏性能?

  12. 如何减少 React Bundle 体积?

  13. React 为什么会出现内存泄漏?如何避免?

# React Native

  1. React Native 为什么性能不如 Native?

    答:React Native 并不是简单套壳,而是在 JS 层运行 React 逻辑,通过 JS 与 Native 通信调用原生能力。性能差异主要来自跨语言通信、JS线程和Native线程之间的数据传递,以及部分复杂 UI 需要经过额外转换。

    RN 架构是什么?

    答:旧架构

    React Component
    
    ↓
    
    JS Thread
    
    ↓
    
    Bridge
    
    ↓
    
    Native Module
    
    ↓
    
    Android/iOS
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    新架构:

    JS
    
    
    ↓
    
    
    JSI
    
    
    ↓
    
    
    TurboModule/Fabric
    
    
    ↓
    
    
    Native
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    JS 和 Native 怎么通信?

    答:使用native module建立一个桥梁,在原生的位置写方法暴露出来,然后在桥调用原生方法,再用promise方法往JS层暴露方法,从而达到通信

    Bridge 有什么问题?

    答:Bridge 是异步通信,需要序列化和反序列化数据,大量通信时会产生性能瓶颈。

  2. RN 页面卡顿如何排查?

    答:当页面有卡顿的现象,首先使用React DevTools Profiler去进行排查,看看每个组件的调用渲染次数

    JS线程阻塞

    原因:大量计算、JSON解析、高频setState

    解决:优化计算、使用memo、移到Native

    大量render

    答:解决React.memo、useMemo、useCallback、状态拆分

    动画执行

    答:普通 Animated 如果运行在 JS Thread,会受到 JS 阻塞影响。可以使用 Reanimated,将动画逻辑放到 UI Thread 执行,提高流畅度。

    图片加载

    答:可以使用懒加载,图片压缩、缓存、CDN

    Native耗时

    答:检查 Native Module 是否存在耗时操作,例如蓝牙扫描、文件处理、大量数据解析,避免阻塞主线程,可以放到后台线程执行。

  3. RN 为什么 FlatList 比 ScrollView 性能好?

    答:FlatList 基于 VirtualizedList 实现,通过窗口化渲染,只维护当前可见区域和附近的数据,而ScrollView 会把所有数据线渲染出来

    FlatList原理?

    答:

    VirtualizedList?

    答:

    如何优化 FlatList?

    答:配置好渲染数量,每一个item的高度固定好,

  4. RN 动画为什么推荐 Reanimated?

    答:Reanimated 推荐使用是因为动画计算可以运行在 UI Thread,而不是 JS Thread。当 JS 线程阻塞时,普通动画可能卡顿,而 Reanimated 可以保持动画流畅。

  5. React Native 的渲染流程是什么?

  6. Native Module中的Promise和Callback区别?

  7. Native EventEmitter原理?

  8. TurboModule是什么?

  9. 什么是 JSI?

# App发布与Native方向

  1. RN App启动流程是什么?

    答:App启动时,Native 首先启动 Application,然后创建 React Native Runtime,加载 JS Bundle,初始化 ReactInstanceManager,创建 JS 与 Native 通信环境,最后渲染 React Component。

# BLE

  1. BLE 为什么会断开?如何提高稳定性?

    答:断开主要会有异常和正常,通过 manualDisconnect 标识判断主动断开。如果主动断开,设置 true,断开完成后释放资源并恢复默认状态。如果 disconnect 时标识为 false,则认为异常断开,进入重连流程。还有,APP退到后台的情况,可能实际断开了,但是状态还是记录着未断开,这种情况需要监听APP的生命周期,后台回到前台的时候,要先去判断一下蓝牙的状态再进行通信。还有要监听好设备的蓝牙开关和权限问题。

  2. BLE 数据高频返回如何避免页面卡顿?

    答:BLE 数据频率较高时,如果每次收到数据都 setState,会导致 React 高频 render。因此会使用 ref 或 buffer 暂存数据,根据一定时间间隔或者数据数量批量更新 UI。

    BLE 50次/s
    
    
    ↓
    
    
    buffer
    
    
    ↓
    
    
    500ms flush
    
    
    ↓
    
    
    UI更新
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

# 部署

  1. Vite开发环境为什么快?

    Vite 开发环境快主要是因为利用浏览器原生 ESM 能力,不需要像 Webpack 一样启动时提前打包整个项目,而是按需加载模块。同时 Vite 使用 esbuild 进行依赖预构建,速度远快于传统 JavaScript 打包工具。

  2. Vite生产环境为什么还需要Rollup?

    Vite开发环境主要利用ESM实现快速启动,而生产环境仍然使用Rollup进行打包,因为生产环境更关注代码压缩、Tree Shaking、资源优化以及兼容性。

  3. ESM是什么?

    ESM是JavaScript官方模块化规范,通过import/export实现模块管理。相比CommonJS,它具有静态分析能力,可以被浏览器直接支持,同时方便Tree Shaking优化。

  4. HMR怎么实现?

    Hot Module Replacement 热模块替换

    Vite通过监听文件变化,利用WebSocket通知浏览器模块更新,然后基于ESM重新请求变化模块,实现局部替换。React项目中结合Fast Refresh,可以做到代码更新但保留组件状态。

  5. Vite和Webpack区别

    Vite 和 Webpack 最大区别在于开发环境的构建方式。

    Webpack 在开发启动时,会先分析整个项目依赖关系,然后进行打包生成 bundle,项目越大,启动时间越长。

    Vite 利用浏览器原生 ESM 能力,开发环境不需要提前打包整个项目,而是启动 Dev Server,当浏览器请求某个模块时,再按需加载对应模块,因此启动速度更快。

    同时 Vite 使用 esbuild 对依赖进行预构建,提高依赖处理速度。

    在生产环境中,Vite 和 Webpack 都需要进行打包优化,Vite 通常使用 Rollup 完成生产构建。

  6. Tree Shaking原理

    Tree Shaking 是基于 ES Module 静态分析能力实现的代码消除技术,它会分析模块中哪些代码被引用,哪些代码没有被使用,然后在生产打包阶段删除未使用代码,从而减少最终 bundle 体积。

    因为 CommonJS 是运行时加载,模块引用关系只有运行时才能确定,而 ESM 是静态结构,打包工具在编译阶段就可以分析依赖关系。

  7. 为什么ESM比CommonJS适合前端

    ESM 是 JavaScript 官方模块规范,使用 import/export,并且模块依赖关系在编译阶段就可以确定,因此支持静态分析、Tree Shaking 和代码分割。同时浏览器原生支持 ESM,可以直接通过 script type="module" 加载。

  8. HMR为什么能保留React状态

    HMR 能保留 React 状态主要依赖 React Fast Refresh 机制。它不会刷新整个页面,而是替换发生变化的组件模块,并尝试保留组件实例和 Hooks 状态。

    流程:

    修改组件代码
    ↓
    HMR通知浏览器
    ↓
    React Fast Refresh判断组件是否可以热替换
    ↓
    保留Hooks状态
    ↓
    重新执行组件
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    如果组件结构变化较大,例如 Hook 顺序变化、组件类型变化,React 无法安全保持状态,就会重新初始化组件。

  9. Webpack Loader 和 Plugin 区别?

  10. Webpack 构建流程是什么?

  11. Vite 为什么生产环境还需要打包?

  12. 如何优化 Webpack 构建速度?

  13. 前端项目如何做 CI/CD?

  14. Docker 部署前端项目流程?

上次更新: 2026/08/30, 14:56:01
Vue性能优化
封装 axios 模块

← Vue性能优化 封装 axios 模块→

最近更新
01
Flutter入门
08-26
02
Dart入门
08-26
03
业务面试题
08-24
更多文章>
Theme by Vdoing | Copyright © 2021-2026 WeiXiaojing | 友情链接
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式