Можно ли внедрить пользовательские атрибуты/свойства в собственные веб-компоненты?

Я изучаю веб-компоненты (нативные и с фреймворками). Можно ли внедрить свойства в собственный компонент, как я могу сделать, например, в Vue.js?

Это мой-component.js:

const templateComponent = document.createElement('template');
templateComponent.innerHTML = `<div>{{ test }}</div>`;

class MyComponent extends HTMLElement {

    connectedCallback() {
        this._container = this.querySelector("DIV");
    }

}

window.customElements.define("my-component", MyComponent);

Это index.html:

<!doctype html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>

<my-component test="Does this work?"></my-component>


<script src="my-component.js"></script>

</body>
</html>

person andreas    schedule 26.04.2019    source источник


Ответы (1)


Да и нет.

Там нет ничего встроенного для шаблонов. Но это не значит, что вы не можете этого сделать.

function render(el) {
  el.shadowRoot.innerHTML = `<div>${el._test}</div>`;
}

class MyComponent extends HTMLElement {
  static get observedAttributes() {
    return ['test'];
  }

  constructor() {
    super();
    this.attachShadow({mode: 'open'});
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    if (oldVal !== newVal) {
      this[`_${attrName}`] = newVal;
      render(this);
    }
  }
}

window.customElements.define("my-component", MyComponent);
<my-component test="Does this work?"></my-component>
<my-component test="Yes it does"></my-component>

Вы используете observedAttributes, чтобы указать, какие атрибуты вы хотите отслеживать для изменений. И вы используете attributeChangedCallback в качестве обработчика, когда один из них действительно изменяется.

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

Что-то более сложное потребует более сложного алгоритма.

Некоторые люди скажут вам использовать LITHtml. Я нахожу это раздражающим. Большинство моих компонентов очень маленькие и не нуждаются в сложности.

Расширенный

Да, вы можете передать функцию обратного вызова в виде строки. Другими словами, вы передаете имя функции обратного вызова в виде строки, а затем в своем компоненте вызываете eval. НО я бы не рекомендовал это. Это имеет много ограничений и может быть использовано для злых и гнусных целей. :)

Вместо:

  • Укажите свойство компонента, которое можно установить для функции обратного вызова.
  • Предоставьте функцию для компонента, который вы бы вызвали с помощью функции обратного вызова.
  • Отправляйте события из компонента, и пусть addEventListener сделает это за вас. Можете ли вы предоставить более подробную информацию о том, что вы хотите сделать с функцией

Вот два полезных вопроса/ответа: функция обратного вызова события веб-компонента в теге * can я передаю функцию как атрибут веб-компоненту?

ОБНОВИТЬ

Был задан вопрос, как избежать рендеринга чаще, чем нужно, когда установлено несколько атрибутов или свойств. Это часто называют «разоблачением».

Вот один из вариантов:

let renderTimeout = null;
function render(el) {
  if (renderTimeout) {
    clearTimeout(renderTimeout);
  }

  renderTimeout = setTimeout(() => {
    el.shadowRoot.innerHTML = `<div>${el._test}</div>`;
  }, 0);
}

Это установит тайм-аут 0, что означает, что это произойдет, как только это будет возможно, часто, как только текущий код завершит работу. Затем произойдет операция рендеринга.

person Intervalia    schedule 26.04.2019
comment
могу ли я также передавать функции (может быть, также в виде строки) компоненту? - person andreas; 10.05.2019
comment
Смотрите мой развернутый ответ. Можете ли вы предоставить более подробную информацию о том, что вы хотите сделать с функцией. - person Intervalia; 10.05.2019
comment
Расширенный ответ абсолютно подходит для того, что я хочу сделать. Спасибо :) - person andreas; 10.05.2019
comment
Есть ли способ предотвратить двойной вызов render(this) при установке двух атрибутов подряд. - person sabithpocker; 08.06.2019
comment
см. мое обновление для одного из способов устранения дребезга функциональности. - person Intervalia; 08.06.2019