【问题标题】:Why does setting textContent cause layout thrashing?为什么设置 textContent 会导致布局抖动?
【发布时间】:2013-06-16 12:03:14
【问题描述】:

This blog post 建议 textContent 优于 innerText 以避免布局抖动。但它专注于检索元素的文本;对于 setting 元素文本,情况正好相反——至少在以下示例中是这样。

此示例使用 innerText 并且不会产生布局抖动:

<style>
    #test {
        background-color: blue;
        float: right;
        width: 100px;
        height: 100%;
    }
</style>
Test test test
<div id="test"></div>
<script>
    setInterval(function() {
        document.querySelector('#test').innerText = 'innerText';
    }, 100);
</script>

但是将 innerText 替换为 textContent 并观察它的颠簸:

有人可以解释这种行为吗?我可以做些什么来避免布局颠簸并仍然以基于标准的方式更改元素的文本?

【问题讨论】:

  • 我会避免innerText:它是非标准的并且在实现上差异很大,甚至在 Firefox 中也没有实现。如果你只是附加一个文本节点会发生什么? var textNode = document.createTextNode("innerText"); document.getElementById("test").appendChild(textNode)

标签: javascript html performance dom


【解决方案1】:

除了Benjamin answer,我注意到当nodeValueinnerText 的值与前一个不同时,整个文档布局也被丢弃,如您在此处看到的:http://jsfiddle.net/5N7Rr/15/

(全屏,在新标签页中打开)

浏览器会丢弃整个布局,因为他不知道元素的大小,因此避免整个文档丢弃的技巧是设置固定的heightwidth 并将overflow 设置为hidden (重要的)。这样你就可以告诉浏览器,无论元素的内容是什么,它都不会退出元素边界。

编辑 30/11/2020:我还需要添加 CSS property contain: strict 以明确告诉浏览器内容不会退出容器。

小提琴:http://jsfiddle.net/u9pra25f/

和证明(再次全屏)。请注意布局更新如何仅影响元素:

【讨论】:

  • 这似乎不再起作用了。小提琴中的示例似乎每次更新时都会计算整个页面(包括结果 iframe 之外的区域)的布局。
  • 你是对的@Nnnes,它现在说“需要布局 5 of 6”而不是“2 of 2”的节点。似乎使整个布局无效。将分析原因。
  • 如果我添加 CSS contain: strict 它会再次显示“2 of 2”,但不会将 div 显示为布局根。我不知道是不是 Chrome 版本之间的输出信息发生了变化,还是它仍然不是根层。
【解决方案2】:

问题:

你是对的!就像你观察到的那样。设置textContent 确实会导致抖动。

这是DOM specification 必须说的话:

DOMString 类型的

textContent,在 DOM Level 3 中引入

此属性返回此节点及其后代的文本内容。定义为null时,设置无效。 在设置时,此节点可能具有的所有可能的子节点都将被删除,如果新字符串不为空或 null,则替换为包含此属性设置为的字符串的单个 Text 节点。

修复

一种非颠簸的方法是获取元素的文本节点并修改它们,而不是使用textContentinnerText(这是非标准的)。

var test = document.getElementById("test");
var a = document.createTextNode("");
test.appendChild(a);
setInterval(function(){
    a.nodeValue = "Test test test";
},100);

Here is a working fiddle

当然,如果实际文本会发生变化,则必须进行绘制以更新您所看到的内容。

【讨论】:

  • 很好的答案。我还发现了这个 Mozilla 错误,它记录了一些本地优化此案例的努力:bugzilla.mozilla.org/show_bug.cgi?id=725221
  • 我必须补充一点,nodeValue 的作用与innerText 相同。如果值相同,布局不会被丢弃,但当值不同时,布局被丢弃与textContent 完全相同:jsfiddle.net/5N7Rr/15i.imgur.com/Yvm0mmK.gifv。 Pretty dump 重新渲染整个文档的布局,因为一个小组件的大小是相同的。
猜你喜欢
  • 2021-06-09
  • 1970-01-01
  • 2012-08-19
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
相关资源
最近更新 更多