Веб-компонент offsetHeight / offsetWidth 0 при подключении - PullRequest
2 голосов
/ 18 июня 2019

Я пытаюсь преобразовать мою библиотеку в веб-компонент, и у меня возникла проблема с тем, когда сказать, что компонент был размечен.

Веб-компоненты имеют функцию обратного вызова под названием connectedCallback, котораяПохоже, это может быть то, что мне нужно, но при проверке себя в обратном вызове мои измерения смещения оба равны нулю:

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

Когда я ставлю в очередь запрос измерений, измерения там, так что когда-то междупри подключении к веб-компоненту и достижении очереди событий следующего элемента веб-компонент раскладывается механизмом браузера, получая правильные значения измерений:

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

Мне интересно, есть ли обратный вызов, чтобы сообщить, когда макетсобытие произошло?

Ответы [ 2 ]

2 голосов
/ 18 июня 2019

Эти значения зависят от всего DOM, поэтому необходимо перерисовать DOM. , который еще не произошел .

Если бы каждый элемент вызывал перерисовку DOM, мы бы все жаловались на производительность.

Браузер решает (логика браузера), когда делать перерисовку DOM.

Обычный и принятый способ выполнения кода после перерисовка DOM - это setTimeout( FUNC , 0 )

, так что строго говоря, это НЕ force перерисовка DOM, браузер все еще решает, когда перерисовывать
Если у вас есть долго работающий скрипт .... FUNC выполнит после долго работающий скрипт будет сделан.

Да, Событие было бы неплохо ...
, но это занимает циклы ЦП ... и в 997 случаях из 1000 вам не нужна информация
.. таким образом, НЕТ события

Таким образом, в 0,03% случаев, когда вам нужна информация о DOM, вы делаете setTimeout

Обратите внимание, что это не относится к пользовательскому элементу, для вызовов appendChild применяется то же самое.

Если у вас есть sh * pload компонентов, которым нужна эта информация о смещении, вы могли бы захотеть взглянуть на Framework, который выполняет виртуальное DOM-диффузирование

Больше фона: Средний: Что за черт перекрасить / перекрасить (2019)

2 голосов
/ 18 июня 2019

Я создал простой компонент без shadowDOM. Я написал следующий код в конструкторе:

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)});

И не получил выхода. Таким образом, ни одно из этих событий не запускается в веб-компоненте.

Затем я добавил этот код вне компонента:

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.

...