【问题标题】:Whether dom-manipulation requires a refresh?dom 操作是否需要刷新?
【发布时间】:2021-09-30 12:04:13
【问题描述】:

我对 DOM 操作有疑问。 dom-manipulation 是否需要刷新?或者 DOM 操作什么时候需要刷新?我看到一些网站在更新它们的某些部分时不断加载。 还, react.js 在处理前端开发时如何帮助避免此类问题?

【问题讨论】:

  • 每个问题问 一个 问题,而不是两个。以上至少有两个。
  • 在这种情况下,您如何定义“刷新”?

标签: javascript html css reactjs web


【解决方案1】:

我对 DOM 操作有疑问。 dom-manipulation 是否需要刷新?

这取决于您所说的“刷新”是什么意思。我至少能想到您可能的意思的三件事:

  • “刷新”就像在页面上按 F5 或点击重新加载按钮

  • “刷新”类似重新计算元素的位置;这更正确地称为“回流”

  • “刷新”就像在屏幕上重绘元素(“重绘”)

重新加载

不,它不会,事实上,如果您重新加载页面,您使用基于浏览器的代码对 DOM 所做的更改将被清除。这是一个非常简单的 DOM 操作示例;直到最后都没有重新加载,完成后你可以看到之前所做的更改被清除了(然后,由于代码也被重新加载,我们从头开始,所以一切都重新开始):

for (let i = 0; i < 5; ++i) {
    delayedAdd(i);
}

function delayedAdd(value) {
    setTimeout(() => {
        // DOM manipulation
        const p = document.createElement("p");
        p.textContent = value;
        document.body.appendChild(p);
        if (value === 4) {
            // Refresh after the last one -- wipes out what we've done
            setTimeout(() => {
                location.reload();
            }, 800);
        }
    }, value * 800);
}

回流

一些 DOM 操作会触发重排,是的;或者更准确地说,做一些事情(可能只是获取元素的当前clientLeft 属性值)会触发重排,而重排可能涉及重新计算布局,这可能很昂贵。代码可能会导致重复回流,包括导致重复重新计算布局,执行一系列操作。 This list from Paul Irish 声称是“什么迫使布局/回流。综合列表。” Paul Irish 在这个领域经验丰富,在业内享有盛誉,所以这份名单很可能是准确的(尽管没有人是完美的,而且这些事情有时会随着时间的推移而改变)。该页面还提供了一些关于如何避免重排(或更准确地说,是如何避免重新计算布局)的指导。

这是导致不必要的布局重新计算的代码示例:

const elementLefts = [];

// This loop triggers layout recalculation 10 times
for (let n = 0; n < 10; ++n) {
    const span = document.createElement("span");
    span.textContent = n;
    document.body.appendChild(span);
    // Triggers layout recalcuation every time:
    elementLefts.push(span.offsetLeft);
}

console.log(elementLefts.join(", "));

我们可以在循环之后得到相同的信息,并且只触发一次布局重新计算:

const spans = [];

// This loop triggers layout recalculation 10 times
for (let n = 0; n < 10; ++n) {
    const span = document.createElement("span");
    span.textContent = n;
    document.body.appendChild(span);
    spans.push(span);
}

// Triggers one layout recalcuation, because nothing has changed between
// times we get `offsetLeft` from an element
const elementLefts = spans.map(span => span.offsetLeft);
console.log(elementLefts.join(", "));

重绘

浏览器一直在重新绘制屏幕,​​通常每秒 60 次(如果运行它的系统具有更高的刷新率,则甚至更多),除非它被 UI 线程(共享与主要的 JavaScript 代码)。 DOM 操作不会导致这种重绘(尽管更改 DOM 可能会改变所绘制的内容,这反过来可能会阻止浏览器重用它上次获得的一些绘制信息)。


另外,react.js 在处理前端开发时如何帮助避免此类问题?

他们可以通过使用导致重新计算的原因的知识并避免做导致它们进入循环的事情等来最小化布局重新计算来帮助回流。也就是说,它们不是灵丹妙药,就像他们拥有的其他一切一样缺点和优点。

【讨论】:

  • 正要将此标记为重复并指向另一个“回流何时发生”的答案,直到我读到此并意识到这是对未提出的 X/Y 问题的一个非常好的答案
  • @slebetman - :-) 如果您有一个很好的“回流何时发生”问题,您会在 cmets 中发布指向它的链接(此处或上述问题)?我可以使用阅读器,发现它的人可能也可以使用。谢谢!
猜你喜欢
  • 2013-12-16
  • 1970-01-01
  • 1970-01-01
  • 2012-09-21
  • 2021-10-01
  • 2020-10-04
  • 2021-03-29
  • 2017-04-23
  • 1970-01-01
相关资源
最近更新 更多