为什么 JS 代码执行了,但页面没马上变?

「我明明写了 element.textContent = 4,为什么没看到页面马上变?」

这个问题,其实触到了浏览器渲染机制的核心:
JS 执行 和 页面绘制 并不是同一件事。

一、JS 的确"立即执行"了

当我们写下:

ini 复制代码
document.querySelector('li:nth-child(2)').textContent = 4;

这段代码会立刻:

  1. 找到目标 <li>;
  2. 修改其在 DOM 树 中的文本节点;
  3. 内存中的 DOM 已经更新为 "4"。

到这里为止:

  • JS 执行是同步的;
  • DOM 确实被改了;
  • 但屏幕上还没"画"出变化。

二、为什么看不到变化?

因为浏览器有一套 批量渲染机制。

它不会在每次 DOM 改动后立即刷新,而是:

等当前 JS 任务执行完后,在这一帧的渲染阶段 统一绘制。

如果此时已错过渲染时机,就会顺延到 下一帧。

三、浏览器的渲染循环(Render Loop)

浏览器的刷新循环大约每 16.6ms 触发一次(对应 60fps),

流程大致是:

阶段 内容
① 执行 JS(修改 DOM)
② JS 任务结束(Event Loop 检查)
③ Layout(计算布局)
④ Paint + Composite(绘制像素)

这意味着:

  • JS 线程没空时,渲染线程没法绘制;
  • 浏览器会等到 JS 任务结束后再绘制;
  • 如果 JS 执行时间太长,错过绘制时机,就会推迟到下一帧。

四、一个实验验证一下

ini 复制代码
const el = document.querySelector('li:nth-child(2)');
el.textContent = 4;
while (true) {} // 无限循环

结果:

页面不会立刻显示"4",因为 JS 主线程被卡死,浏览器无法进入渲染阶段。

五、完整的时间线

css 复制代码
┌───────────────┐
│ JS 修改 DOM   │  ← 同步执行,立即生效(内存)
└──────┬────────┘
       ↓
  [事件循环等待]
       ↓
┌───────────────┐
│ Layout 阶段   │
│ Paint 阶段    │ ← 浏览器统一绘制
└───────────────┘
阶段 线程 是否同步 屏幕是否更新
JS 执行 JS 主线程 ✅ 是 ❌ 否
DOM 更新 内存结构 ✅ 是 ❌ 否
渲染绘制 渲染线程 ❌ 否 ✅ 是

六、关键结论

element.textContent = 4 会立即修改 DOM,但不会立即触发渲染。

浏览器会在当前 JS 任务结束后、本帧的绘制阶段 统一绘制。

若本帧的绘制时机已过,才会顺延到下一帧。

相关推荐
小poop6 小时前
CSS 基础与实战:从入门到精通网页美化
前端
Csvn8 小时前
运行时性能
前端
Never_every999 小时前
位图转矢量工具哪个好?实测抠抠图AI位图转矢量工具
大数据·前端
paopaokaka_luck9 小时前
宠物门店经营管理系统(销售与库存联动、进货自动记账、 退换与退款关联、员工个人业绩、ECharts 经营分析、滞销识别与客户分层、宠物档案年龄计算)
前端·javascript·spring boot·mysql·echarts·mybatis·1024程序员节
空中湖10 小时前
用 React 写数据大屏:为什么我不建议用图表库
前端·react.js·前端框架
欣欣之王来了11 小时前
原始HTML插值:v-html指令的使用与安全风险
前端·学习·架构·项目·vue3教程
IT_陈寒11 小时前
Redis的LRU淘汰策略坑了我一整天
前端·人工智能·后端
计算机魔术师11 小时前
砍半价格、参数再涨,国产旗舰追到 Opus 鼻尖了
前端
特立独行的猫A12 小时前
10 MB 的桌面 AI 客户端:用仓颉 + 系统 WebView 替代 Electron
前端·harmonyos
修炼的dance12 小时前
白底图存JPG,sharp开mozjpeg背景杂点少近三成
前端