WHAT - Vercel react-best-practices 系列(五)

文章目录

前言

react-best-practices

React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.

Guidelines

在这个系列,我会逐条拆解,每一条都给出:

  • 核心问题是什么
  • 为什么会慢(本质原因)
  • 典型业务场景
  • 反例代码
  • 推荐写法
  • 在 React / Next.js 中的实际收益

JavaScript Patterns

这是系列的第五部分。

这一部分其实非常"工程味" ,不再是 React 专属,而是 JS / DOM / 数据结构层面的硬功夫

这些点看起来"小",但在表格、列表、频繁交互 里都是实打实的性能差异

Batch DOM CSS changes via classes

样式一次性切换,不要逐条改

核心问题

每一次:

js 复制代码
el.style.xxx = ...

都可能触发:

  • style recalculation
  • layout
  • paint

多次修改 = 多次成本

反例:逐条改 style

js 复制代码
el.style.width = '200px'
el.style.height = '100px'
el.style.background = 'red'

推荐:class 批量切换

js 复制代码
el.classList.add('active')
css 复制代码
.active {
  width: 200px;
  height: 100px;
  background: red;
}

浏览器只需要一次 style 计算

典型场景

  • hover / active 状态
  • 拖拽高亮
  • 表格行选中
  • 动态主题切换

一句话总结

DOM 改一次,CSS 管所有

Build index maps for repeated lookups

多次查找,用 Map,不要 filter / find

核心问题

js 复制代码
array.find(...)
  • O(n)
  • 在 render / 循环中反复执行 → O(n²)

反例

ts 复制代码
items.map(item => {
  const user = users.find(u => u.id === item.userId)
  return { ...item, user }
})

推荐:构建索引 Map

ts 复制代码
const userMap = new Map(users.map(u => [u.id, u]))

items.map(item => {
  const user = userMap.get(item.userId)
  return { ...item, user }
})

复杂度从 O(n²) → O(n)

典型场景

  • 表格数据 join
  • id → entity 映射
  • 权限校验
  • diff 对比

一句话总结

先建索引,再查数据

Cache repeated function calls

相同输入,不要重复算

核心问题

ts 复制代码
formatPrice(price)

如果:

  • 在 render 中
  • 在循环里
  • 输入值重复

白算很多次

反例

ts 复制代码
{items.map(i => (
  <span>{formatPrice(i.price)}</span>
))}

推荐:简单 memo

ts 复制代码
const cache = new Map()

function formatPriceCached(price) {
  if (cache.has(price)) return cache.get(price)

  const result = formatPrice(price)
  cache.set(price, result)
  return result
}

React 中更推荐:

ts 复制代码
const formatted = useMemo(
  () => formatPrice(price),
  [price]
)

一句话总结

算过的值,记下来

Use toSorted() instead of sort() for immutability

不要原地排序

核心问题

js 复制代码
array.sort()
  • 原地修改
  • 破坏不可变数据
  • React 中可能导致 状态错乱

反例

ts 复制代码
const sorted = items.sort((a, b) => a.age - b.age)
setItems(sorted)

items 被直接改了

推荐:toSorted(ES2023)

ts 复制代码
const sorted = items.toSorted((a, b) => a.age - b.age)
setItems(sorted)

返回新数组,原数组不变

兼容方案

ts 复制代码
[...items].sort(...)

一句话总结

React 状态 = 不可变

Early length check for array comparisons

先比长度,再比内容

核心问题

ts 复制代码
arraysEqual(a, b)

如果:

  • 长度不同
  • 却仍然逐项对比

纯浪费

反例

ts 复制代码
function isEqual(a, b) {
  return a.every((v, i) => v === b[i])
}

推荐:提前剪枝

ts 复制代码
function isEqual(a, b) {
  if (a.length !== b.length) return false

  return a.every((v, i) => v === b[i])
}

场景

  • memo / shouldComponentUpdate
  • diff 算法
  • selection 对比
  • 权限数组变化检测

一句话总结

先 cheap check,再 expensive check

JS 性能心法

少动 DOM
少扫数组
少算重复
不改原数据
先剪枝

总结

JS 性能不是靠"更快算法",而是靠"少做事"

相关推荐
念念不忘 必有回响6 小时前
viepress:vue组件展示和源码功能
前端·javascript·vue.js
C澒6 小时前
多场景多角色前端架构方案:基于页面协议化与模块标准化的通用能力沉淀
前端·架构·系统架构·前端框架
崔庆才丨静觅6 小时前
稳定好用的 ADSL 拨号代理,就这家了!
前端
江湖有缘6 小时前
Docker部署music-tag-web音乐标签编辑器
前端·docker·编辑器
早點睡3906 小时前
高级进阶 React Native 鸿蒙跨平台开发:react-native-device-info 设备信息获取
react native·react.js·harmonyos
恋猫de小郭7 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅14 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606114 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了14 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅14 小时前
实用免费的 Short URL 短链接 API 对接说明
前端