为什么你的页面总是卡顿?不一定是代码烂

0 阅读3分钟

一、误区:卡顿 = 技术不行 / 框架不行

常见反应:

  • “是不是 Vue 太慢?”
  • “是不是该上虚拟滚动?”
  • “是不是要重写一遍?”

但真实情况是:

👉 大部分卡顿,来自几个固定的低级问题

而且这些问题:

  • 和框架关系不大
  • 和架构关系不大
  • 和“你会不会写高级代码”也关系不大

本质是:

对浏览器渲染机制不敏感


二、工程化视角:卡顿的本质是“主线程被占满”

浏览器一帧的时间是:

👉 16.6ms(60FPS)

在这 16.6ms 内,要完成:

  1. JS 执行
  2. 样式计算
  3. 布局(回流)
  4. 绘制(重绘)

只要其中任何一步超时:

👉 就会掉帧 → 卡顿

所以性能问题的核心判断是:

是谁占满了主线程?


三、最常见的 4 个卡顿来源(重点)


1️⃣ 回流 & 重绘:最隐蔽的性能杀手

很多人无意中在做这种操作:

el.style.width = '100px';
console.log(el.offsetWidth);
el.style.width = '200px';

👉 读 + 写 + 读 = 强制回流


✅ 常见踩坑

  • 频繁修改 DOM 样式
  • 在循环中操作 DOM
  • 一边读布局,一边写布局

✅ 优化方法

① 批量修改样式

el.style.cssText = 'width:100px;height:100px;';

② 读写分离

👉 先读 → 再统一写


③ 用 transform 替代布局属性

transform: translateX(100px); ✅
left: 100px; ❌

🎯 核心结论

能不触发布局,就不要触发布局


2️⃣ 图片资源:最容易被忽略的大头

很多页面卡,不是因为 JS:

👉 是图片太大


✅ 常见问题

  • 一张图 2MB+
  • 用原图直接展示(未压缩)
  • 没有使用合适尺寸

✅ 优化方法

① 控制图片尺寸

👉 显示 300px,就不要加载 2000px 图


② 使用现代格式

  • WebP
  • AVIF

③ 懒加载

<img src="xx.jpg" loading="lazy" />

🎯 核心结论

图片是“最贵资源”,但最容易优化


3️⃣ 长列表:DOM 数量爆炸

典型场景:

  • 渲染 1000+ 条数据
  • 表格 / 聊天记录 / 商品列表

结果:

👉 页面直接卡死 or 滚动掉帧


✅ 问题本质

不是“数据多”,而是:

DOM 节点太多


✅ 优化方法

① 虚拟列表(只渲染可视区域)

核心思想:

👉 只渲染 10 条,看起来像 1000 条


② 分批渲染

requestAnimationFrame(() => {
  // 分批插入 DOM
});

③ key 稳定

避免重复销毁 / 创建节点


🎯 核心结论

不是数据压垮页面,是 DOM 压垮页面


4️⃣ 事件滥用:隐形性能消耗

典型问题:

  • scroll 事件里疯狂计算
  • resize 触发大量逻辑
  • 每个元素都绑定事件

✅ 常见错误

window.addEventListener('scroll', () => {
  // 大量计算
});

👉 每一帧都在跑


✅ 优化方法

① 节流(throttle)

const throttle = (fn, delay) => {
  let last = 0;
  return (...args) => {
    const now = Date.now();
    if (now - last > delay) {
      fn(...args);
      last = now;
    }
  };
};

② 防抖(debounce)

适合 resize / input


③ 事件委托

👉 减少监听器数量


🎯 核心结论

不是事件多,而是“高频 + 重逻辑”


四、一个简单有效的排查顺序(重点)

当你遇到卡顿,不要乱优化,按这个顺序查:


① 看 DOM 数量

👉 Elements 面板:

  • 是否上千节点?

② 看图片

👉 Network 面板:

  • 有没有大图?

③ 看事件

👉 有没有 scroll / resize 重逻辑?


④ 再看 JS / 框架问题

👉 最后才是代码层面优化


五、真正的分水岭:不是“优化能力”,而是“避免问题”

普通开发:

👉 卡了再优化

高手:

👉 一开始就避免:

  • 不乱操作 DOM
  • 不加载大图
  • 不直接渲染长列表
  • 不滥用事件

六、落地建议(立刻见效)


1️⃣ 给自己一个“性能红线”

  • DOM < 500(普通页面)
  • 单图 < 200KB

2️⃣ 所有高频事件默认加节流

👉 scroll / resize / mousemove


3️⃣ 默认考虑“是否会触发回流”

写代码时多问一句:

这行代码会不会影响布局?


七、总结一句话

大多数卡顿,不是因为你不会优化,而是因为你在“无意识制造问题”。