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 性能不是靠"更快算法",而是靠"少做事"

相关推荐
天问一1 小时前
Cesium 处理屏幕空间事件(鼠标点击、移动、滚轮)的示例
前端·javascript
bjzhang751 小时前
使用 HTML + JavaScript 实现多会议室甘特视图管理系统
前端·javascript·html
qiqiliuwu1 小时前
VUE3+TS+ElementUI项目中监测页面滚动scroll事件以及滚动高度不生效问题的解决方案(window.addEventListener)
前端·javascript·elementui·typescript·vue
LawrenceLan2 小时前
16.Flutter 零基础入门(十六):Widget 基础概念与第一个 Flutter 页面
开发语言·前端·flutter·dart
喔烨鸭2 小时前
antdv编辑表格,根据选择时间区间展示动态列
前端·vue·表格编辑
天天向上10242 小时前
el-table 解决一渲染数据页面就卡死
前端·javascript·vue.js
bjzhang752 小时前
使用 HTML + JavaScript 实现单会议室周日历管理系统
前端·javascript·html
weixin_431600442 小时前
开发中遇到需要对组件库组件结构调整的两种落地方案实践
前端·组件库
Code知行合壹2 小时前
Vue3入门
前端·javascript·vue.js