【问题标题】:What exactly updates when the DOM is manipulated操作 DOM 时究竟更新了什么
【发布时间】:2018-06-11 23:07:10
【问题描述】:

我试图准确了解在 DOM 操作之后使用常规 DOM 更新了什么。

假设我们有下面的 DOM,我使用 javascript 删除了蓝色类的 li。

这是否意味着浏览器查看蓝色类的父级(例如:列表 1 的 id)并重新渲染该 DOM 节点,包括所有子级(减去蓝色类),然后根据任何 css 重新绘制整个页面规则?

我认为这将是过程,但我不确定,也无法在任何地方找到任何具体示例。

 <div>
   <ul id="list1">
     <li> red </li>
     <li class="blue"> blue </li>
     <li> green </li>
    </ul>
    <ul id="list2">
      <li> orange </li>
      <li> gray </li>
      <li> brown </li>
    </ul>
 </div>

【问题讨论】:

  • 这正是浏览器应该做的。

标签: javascript css dom dom-manipulation


【解决方案1】:

这并不那么容易,这是因为您可能不太了解 DOM 更新 + 渲染过程 的工作原理。

DOM 只是一个 javascript 对象,就像任何其他对象一样。

当您执行 DOM 操作时,实际上就像您确实修改了普通对象的属性(虽然很复杂,但仍然如此)。

其中一些 manips 可能确实会弄脏页面的布局和渲染的框架,但通常浏览器会等到它们确实必须执行重绘操作时才会触发这两种算法。这意味着这些算法不会在每次单独的 DOM 操作时触发。

所以要回答这个问题,当 DOM 被操作时,您正在更改 js 对象的属性,并可能设置一个标志来告知布局重新计算和渲染器,它们必须在下次屏幕刷新时启动。

当这些 layout recalc(又名 reflow)和重绘操作真正开始时,不受任何规范的约束,而这正是大多数浏览器会尝试的地方优化,因此很难对它们在任何地方的工作方式有一个明确的说法。 (虽然指定in some cases回流应该同步踢)。
但是我们可以假设,如果没有任何可渲染的内容发生变化,那么这些至少是捷径。

例如,如果在您的示例中 #list1 将其 display CSS-property 设置为 none,那么很可能没有需要重新绘制的内容,如果您确实同步地重新附加了 .blue 元素也是如此。

说得简单点,

// js execution
DOM manip => mark layout as dirty
DOM manip => mark layout as dirty
... there may be a lot here

// Before screen refresh
if(layout.isDirty()) 
  layout.recalc() // will itself mark repaint as dirty if needed
if(renderer.isDirty())
  rendered.repaint()

【讨论】:

    【解决方案2】:

    是的,因为这是删除元素的唯一方法,...通过它的父元素,即.removeChild()。然后,DOM 可能会或可能不会经历所谓的重排,具体取决于更改的结果。

    【讨论】:

    • DOM 不一定要进行回流。如果在 DOM 操作结束时没有发生任何更改(例如,因为您做了 child.remove(); parent.append(child); 并且如果您没有调用回流触发器方法/属性之一,则不应发生回流。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-23
    • 2016-09-10
    • 2023-03-15
    • 2012-10-17
    • 2021-06-04
    • 1970-01-01
    • 2018-07-30
    相关资源
    最近更新 更多