Любой способ сохранить разметку и стиль шаблона elemnt вне строки javascript? - PullRequest
2 голосов
/ 11 июля 2019

Это пример использования пользовательских элементов из developers.google.com :

let tmpl = document.createElement('template');
tmpl.innerHTML = `
  <style>:host { ... }</style> <!-- look ma, scoped styles -->
  <b>I'm in shadow dom!</b>
  <slot></slot>
`;

customElements.define('x-foo-shadowdom', class extends HTMLElement {
  constructor() {
    super(); // always call super() first in the constructor.

    // Attach a shadow root to the element.
    let shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.appendChild(tmpl.content.cloneNode(true));
  }
  ...
});

Хотя это работает, я нахожу этот подход странно уродливым. HTML и CSS должны находиться в файлах .html и .css, а не в строках Javascript.

В то же время я не знаю, как переместить этот контент в файлы .html или .css?

Ну, да, я мог бы заполнить основной HTML-файл, а именно index.html, тегами <template> для всех пользовательских элементов, которые могут быть когда-либо использованы, но не противоречит ли это назначению пользовательских элементов?

<link rel="import"> может быть многообещающим, но оно было отброшено .

Есть ли другие варианты?

(Или я ошибочно нахожу оригинальное решение некрасивым?)

1 Ответ

2 голосов
/ 12 июля 2019

Вы можете использовать fetch(), чтобы получить HTML-файл для содержимого пользовательского элемента.

customElements.define('x-foo-shadowdom', class extends HTMLElement {
    constructor() {
        super()
        this.attachShadow( {mode: 'open'} )
    }

    async connectedCallback() {
        let res = await fetch( 'x-foo.html' )
        this.shadowRoot.innerHTML = await res.text()
    }
}

Примечание: поскольку fetch() и text() являются асинхронными, необходимо добавить async перед connectedCallback() и await перед вызовом метода.

Вы также можете получить отдельный контент CSS, просто используя <link> в коде HTML.


Я ошибаюсь, чтобы найти оригинальное решение некрасиво?

Да, это ужасно. Если вы хотите использовать литерал шаблона, вам не нужно помещать его в элемент <template> и клонировать его.

Вместо этого используйте шаблонный литерал напрямую:

shadowRoot.innerHTML =  `
  <style>:host { ... }</style> <!-- look ma, scoped styles -->
  <b>I'm in shadow dom!</b>
  <slot></slot>
`;

Обратите внимание, что у литералов шаблона есть преимущество перед отдельным HTML: вы можете легко использовать переменные вставки. Пример с добавочным счетчиком кликов:

customElements.define( 'click-counter', class extends HTMLElement {
  connectedCallback() {
    let count = 0
    let sh = this.attachShadow( { mode: 'open' } )    
    this.onclick = () => sh.innerHTML = `<button>${count++}</button>`
    this.click() 
  }
} )
<click-counter></click-counter>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...