Позднее "ручное" обновление элемента в сторону встроенного веб-компонента
У меня есть плагин jQuery (который я не хочу изменять), который динамически создает div
, Кроме того, у меня есть веб-компонент scrollable-div
, который является настраиваемым встроенным расширением от HTMLDivElement
, Поскольку я не имею никакого контроля над тем, как это div
создается плагином jQuery, мне нужно обновить его после создания и после того, как он уже был добавлен в DOM.
class myDiv extends HTMLDivElement {
constructor(...args) {
const self = super(...args);
self.addEventListener('click', (e) => {
e.target.textContent = 'clicked'
})
return self;
}
}
customElements.define('my-div', myDiv, { extends: 'div' });
document.addEventListener('DOMContentLoaded', () => {
// this is where I'm trying to turn the div#upgradeMe into a my-div
upgradeMe.setAttribute('is', 'my-div');
});
<div id="upgradeMe">Click me</div>
Просто добавив is="my-div"
Атрибут, очевидно, не работает, div
просто остается постоянным HTMLDivElement
, Как программно обновить собственный элемент, который уже находится в DOM, до настроенного встроенного веб-компонента?
2 ответа
Это невозможно, потому что элемент уже создан как стандарт <div>
элемент и не идентифицируется при разборе на обновляемые (расширяемые) из-за отсутствия is
приписывать.
Если пользовательский элемент уже определен, единственный возможный обходной путь - заменить существующий клоном (как предложено в комментариях @barbsan).
Короткий путь:
- создать
<template>
элемент - скопировать div
outerHTML
в егоinnerHTML
имущество - замените оригинальный элемент на шаблон
content
сreplaceChild()
class myDiv extends HTMLDivElement {
constructor(...args) {
const self = super(...args);
self.addEventListener('click', (e) => {
e.target.textContent = 'clicked'
})
return self;
}
}
customElements.define('my-div', myDiv, { extends: 'div' });
document.addEventListener('DOMContentLoaded', () => {
// this is where I'm trying to turn the div#upgradeMe into a my-div
upgradeMe.setAttribute('is', 'my-div');
var t = document.createElement( 'template' )
t.innerHTML = upgradeMe.outerHTML
upgradeMe.parentElement.replaceChild( t.content, upgradeMe )
});
<div id="upgradeMe">Click me</div>
Precisions
Когда элемент анализируется, значение is изменяется в соответствии со спецификацией DOM:
Элементы имеют ассоциированное пространство имен, префикс пространства имен, локальное имя, пользовательское состояние элемента, определение пользовательского элемента, значение. Когда элемент создан, все эти значения инициализируются.
Только элементы с действительными is
атрибут идентифицируется как настраиваемый:
Пользовательским состоянием элемента является одно из следующих: "undefined", "fail", "uncustomized" или "custom". Элемент, для которого пользовательское состояние элемента является "ненастроенным" или "нестандартным", называется определенным. Элемент, для которого пользовательское состояние элемента является "пользовательским", называется пользовательским.
Поэтому, если элемент не имеет is
атрибут во время разбора, он не будет настраиваемым. Вот почему вы не можете добавить is
атрибут потом.
Также в спецификации HTML:
После создания пользовательского элемента изменение значения атрибута is не меняет поведения элемента, поскольку он сохраняется в элементе в качестве его значения.
is
Атрибут используется только при создании элемента (во время разбора) для инициализации значения is и не имеет никакого эффекта, если изменен, когда элемент уже создан. В этом смысле значение доступно только для чтения.
Если вы хотите поддерживать все современные браузеры, которые вы не можете настроить встроенными компонентами, Apple заявляет, что они никогда не будут поддерживать is = "" https://github.com/w3c/webcomponents/issues/509