DOM 更新渲染时机

问题

事件循环

  1. 进入到 script 标签,就进入到了第一次事件循环.
  2. 遇到同步代码,立即执行
  3. 遇到宏任务,放入到宏任务队列里.
  4. 遇到微任务,放入到微任务队列里.
  5. 执行完所有同步代码
  6. 执行微任务代码
  7. 微任务代码执行完毕,本次队列清空
  8. 更新 DOM 渲染
  9. 寻找下一个宏任务,重复步骤1

那么在宏任务或微任务中操作 DOM 之后,再获取 DOM 的最新状态或位置,这时 DOM 还没渲染为什么能获取到。

更新 DOM 渲染

首先需要用改变 DOM 才会触发更新 DOM 渲染。如下:

这段代码是同步执行的,因此

能打印最新的值。

此时页面并没有渲染出最新的内容。

这段代码运行效果如下:

这里用到了 alert ,在 chrome 中 alert 会暂停任务执行,相应的事件循环不得运行进一步的任务,并且当前正在运行的任务中的任何脚本都必须阻塞。 因此在 alert 信息弹出,页面显示"测试",说明页面没有渲染。而提示框提示的信息是"测试"。

我们修改下添加宏任务和微任务:

运行效果如下:

微任务提示框时页面没有重新渲染。

宏任务提示框时页面渲染了。

页面渲染不是同步渲染的,而是在一个事件循环微任务执行完之后才会渲染,也就是在一个事件循环内缓存宏任务和微任务的 DOM 操作,最后才一起渲染到页面上。

我们用 document 的 API 修改 DOM 时,在用 document 的 API 获取 DOM 的属性自然也就是最新值。

那该元素在页面的位置和尺寸大小能不能获取到最新的呢?

页面渲染主要分为两个阶段:Reflow(回流)、Repaint(重绘)。

Reflow(回流),有的叫它重排,这个阶段主要是重新触发了 Layout(布局),重新计算元素的所有框位置。

Repaint(重绘),将元素样式绘制在屏幕上。

如果页面的是在微任务之后执行重新渲染,那么在宏任务中修改尺寸时没有触发 Layout(布局)应该获取不到最新尺寸的,我们写个例子看看是不是这样:

运行结果:

运行结果可以看到可以获取到最新的尺寸,我们用 devtool 工具监听页面的渲染过程。

图中看到执行了两个 alert,我们把两个 alert 之间的部分放大看看:

两个 alert 直接触发了 Layout(布局)。

也就是当获取 DOM 尺寸的时候强制执行了 Layout(布局) 后再获取 DOM 的尺寸,但并没有触发重绘,只是触发了布局。

总结

  • DOM 的修改时同步修改。
  • Reflow(回流),通常浏览器会等到宏任务和微任务操作DOM执行完之后再触发它,但是一些 DOM 方法比如获取尺寸 offsetXXX 等会强制触发同步 Relow(回流),以便获取最新值,但不会强制触发 Repaint(重绘)。
  • Repaint(重绘),将元素样式绘制在屏幕上,大多数浏览器会等待下一次屏幕刷新,不同浏览器重绘规则有区别。
相关推荐
PedroQue993 分钟前
v0.2.0 架构升级:class + reactive 重塑状态管理
前端·uni-app
鶴哥只手遮天3 分钟前
Angular 22 源码级深度解析-第 02 章 编译链路总览:从模板字符串到 `ɵɵ` 指令
前端·开源·angular.js
尘世中一位迷途小书童3 分钟前
别再堆万字 Prompt:用 Agent Skills 给团队写一个「前端 Review」Skill
前端·ai编程·cursor
aixingpan5 分钟前
aixingpan.cn API开发文档:api_docs_bichart_common2接口指南
前端·php
super_Omni8 分钟前
text/PDF/Word → 解析成纯文本 → 分词 → 词表匹配 → 加权打分 → 低于阈值
前端·chrome
阶进遐12 分钟前
浏览器工具自制指南·对话导出(3):消息池设计
前端
SameX16 分钟前
HarmonyOS 用 relationalStore 做阅读统计 App —— 5 张表背后的 5 个 schema 决策
前端
LV技术派28 分钟前
【成为 AI Native Builder · 02】什么是 AI Native Builder:一个人 + AI,交付完整闭环
前端·程序员·ai编程
#麻辣小龙虾#1 小时前
网页布局css中flex+margin的组合布局技巧
开发语言·前端·javascript
叼烟扛炮1 小时前
Linux 学习笔记(四十五):Web 安全基石——Cookie、Session 与 HTTPS 原理解析
linux·前端·网络·笔记·学习·tcp/ip·安全