Web 组件 offsetHeight/offsetWidth 连接后为零

Web Component offsetHeight/offsetWidth zero when connected

我正在尝试将我的库转换为 Web 组件,但我遇到了 运行 何时告知组件已布局的问题。

Web 组件有一个名为 connectedCallback 的回调,看起来它可能是我需要的,但是在回调中检查 self 时,我的偏移尺寸均为零:

connectedCallback() {
  console.log(this.offsetWidth, this.offsetHeight);
}

当我对维度查询进行排队时,维度就在那里,所以在 Web 组件连接和事件队列到达下一个项目之间的某个时间,Web 组件被浏览器引擎布局,获得正确的维度值:

connectedCallback() {
  setTimeout(() => console.log(this.offsetWidth, this.offsetHeight), 0);
}

我想知道是否有回调告诉布局事件何时发生?

我创建了一个没有阴影的简单组件DOM。我在构造函数中编写了以下代码:

this.addEventListener('readystatechange', (evt) => {console.log('readystatechange', evt)});
this.addEventListener('load', (evt) => {console.log('load', evt)});
this.addEventListener('progress', (evt) => {console.log('progress', evt)});
this.addEventListener('DOMContentLoaded', (evt) => {console.log('DOMContentLoaded', evt)});

没有输出。因此 none 这些事件在 Web 组件上触发。

然后我在组件外添加了这段代码:

function callback(mutationsList, observer) {
  for(var mutation of mutationsList) {
    if (mutation.type === 'childList') {
      if (mutation.removedNodes.length) {
        console.log(`${mutation.removedNodes.length} child node(s) have been removed.`);
      }

      if (mutation.addedNodes.length) {
        console.log(`${mutation.addedNodes.length} child node(s) have been added.`);
      }
    }
  }
}
var config = { childList: true };
var observer = new MutationObserver(callback);

构造函数的这一行:

observer.observe(this, config);

在我的特定组件上,我的 callback 从未被调用过。

我确实有一个不同的组件更改其子项并调用了回调。

所以,我没有看到任何事件,甚至没有看到组件完全加载时触发的突变观察器。

就我个人而言,我会像您一样使用 setTimeout,因为这似乎是组件完成后获得调用的唯一可靠方式。虽然您可能必须具体说明 setTimeout 的放置位置,以确保您已完全呈现 DOM.

这些值取决于整个 DOM 因此需要 DOM 重绘.. 还没有发生

如果每个元素都会触发 DOM 重绘,我们都会抱怨性能。

浏览器决定(浏览器特定逻辑)何时进行 DOM 重绘。

在 DOM 重绘后 执行代码的通常且可接受的方式是 setTimeout( FUNC , 0 )

所以严格来说这不会强制DOM重绘,它仍然是浏览器决定何时重绘
如果你有一个长 运行 脚本.... FUNC 将在
长 运行 脚本完成后执行

是的,一个活动会很好...
但这需要 CPU 个周期...并且在 1000 个案例中有 997 个你不需要信息
.. 因此没有事件

所以在 0.03% 的情况下你确实需要 DOM 信息你做 setTimeout

请注意,这不是特定于自定义元素的,对于 appendChild 调用同样适用。

如果您有大量需要此偏移信息的组件,您可能想要研究一个执行虚拟 DOM 差异[=14= 的框架]

更多背景:Medium: What the heck is repaint/reflow (2019)