lit-element getElementById в connectedCallback возвращает null

Я помню, что во многих руководствах по веб-компонентам говорится, что connectedCallback хорош для подключения событий DOM или получения некоторых элементов DOM (например, этот). Но я не мог заставить простую программу работать в lit-element:

import { LitElement, html } from 'lit-element';

class MyElement extends LitElement {
  render() {
    return html`<p id="root">template content</p>`;
  }

  connectedCallback() {
    super.connectedCallback();
    this.shadowRoot.getElementById('root'); // null
  }

  firstUpdated() {
    this.shadowRoot.getElementById('root'); // not null
  }
}

Похоже, это работает только в firstUpdated, разве firstUpdate не срабатывает после первого рендеринга? что, если мне нужно настроить некоторые события перед первым рендерингом? почему connectedCallback здесь не работает?


person Hammerhead    schedule 21.02.2021    source источник


Ответы (1)


connectedCallback работает в соответствии со спецификацией, но не делает того, что вы ожидаете.

Эти обратные вызовы срабатывают в разные моменты времени

<my-element myattribute="foo">   1. -> connectedCallback
  <p id="root">
    template content
  </p>
</my-element>  2. -> firstUpdated (LitElement)

1. -> connectedCallback означает, что элемент внедрен в DOM. но его дочерние элементы еще не проанализированы.

Если только вы не используете FireFox (версия до 2021 года !!), который connectedCallback слишком поздно срабатывает на 2. (подтвержденная ошибка)

Думайте об элементах как о водяных шлангах; Подключить означает, что шланг подключен к крану, а не по нему течет вода. Таким образом, вы можете получить доступ к атрибутам данных (свойство шланга) в connectedCallback

Вот почему connectedCallback срабатывает в этот 1. -> момент времени ... вам может понадобиться контент, основанный на его атрибутах. И вы не хотите ждать, пока весь контент будет проанализирован (который потенциально может быть очень большим деревом DOM)

Также обратите внимание, что connectedCallback запускается каждый раз, когда вы перемещаете элемент в DOM.

И если вы погрузитесь глубже, вы также заметите attributeChangedCallback можно запустить до connectedCallback

Обратные вызовы жизненного цикла LitElement - это сахар, они «защищают» вас от (мощного) поведения веб-компонентов «голого железа».

Итак, без LitElement вы можете:

connectedCallback(){
  // 1. -> do stuff
  setTimeout(() => { // no trickery, just wait till that dreaded JS Event Loop is done
    // all children are parsed
    // 2. -> do stuff
  });
}

Подробнее о кровавом обратном вызове см .: дождитесь обновления элемента в connectedCallback : Различия между FireFox и Chromium

person Danny '365CSI' Engelman    schedule 21.02.2021