如何动态设置 Web 组件的属性
How To Set An Attribute Of A Web Component Dynamically
我一直在尝试为我设计的名为 ws-dialog
的自定义 Web 组件设置属性。它总是在代码上添加一个属性undefined
:
<ws-dialog class="global" undefined="add-page-content"></ws-dialog>
我想在这里做的是声明一个像template
这样的属性,而不是undefined
。这是我用于向所有对话目标元素添加 onclick
事件的代码:
function addDialogEvents(target) {
target.addEventListener("click", () => {
let dialog = document.createElement(Dialog.getName());
let body = document.querySelector("body");
dialog.template = "add-page-content";
body.append(dialog);
});
}
这是我的自定义组件的代码:
"use strict";
class Dialog extends HTMLElement {
connectedCallback() {
//Styles for this custom component are declared in a separate CSS module
}
updateContent(id) {
let content = document.querySelector(`template#${id}`).content;
if (content)
this.append(content);
}
attributeChangedCallback(name, oldValue, newValue) {
this.TEMPLATE = "template";
switch (name) {
case this.TEMPLATE:
this.updateContent(newValue);
break;
}
}
static get observedAttributes() {
return [this.TEMPLATE];
}
static getName() {
return "ws-dialog";
}
get template() {
return this.getAttribute(this.TEMPLATE);
}
set template(template) {
this.setAttribute(this.TEMPLATE, template);
}
}
customElements.define(Dialog.getName(), Dialog);
这里有一个 playground,可以帮助您了解什么时候触发了什么方法。
注意何时 以及调用了多少次 observedAttributes
。
这意味着您的 this.TEMPLATE
是 undefined
,因此成为 Array
中的字符串 undefined
<script>
const log = (...args) => {
let div=document.body.appendChild(document.createElement('DIV'));
div.style = `background:${args.shift()};color:white;font:13px Arial`;
div.append(args.join(" "));
}
customElements.define('my-element', class extends HTMLElement {
log() {
log(this.getAttribute("color"), this.outerHTML.split(">")[0],'>', ...arguments);
}
static get observedAttributes() {
log('red', `my-element observedAttributes`);// NO 'this' / Element here!
return ["color"];
}
constructor() { super().log("constructor") }
connectedCallback() {
this.log("connectedCallback" , this.innerHTML || "No innerHTML" );//FireFox difference!
setTimeout(() => this.log(`delayed connectedCallback ${this.innerHTML}`), 0);
}
attributeChangedCallback(name, oldValue, newValue) { // 4th W3C parameter = Namespace (not implemented in Browsers)
this.log("attributeChangedCallback", name, oldValue || "null", newValue);
}
disconnectedCallback(){ this.log("disconnectedCallback") }
})
document.body.onload = () => {
log('magenta', 'onload event');
A.setAttribute("color", "darkolivegreen");
B.innerHTML = "<my-element id=C color=hotpink>Charlie replaced Bravo</my-element>";
B.remove();
}
</script>
<my-element id=A color=green>Alfa</my-element>
<my-element id=B color=blue>Bravo</my-element>
备注:
有用的图表位于:https://andyogo.github.io/custom-element-reactions-diagram/
仅在 FireFox 中执行顺序略有不同,我的建议是不要开发,仅在 Firefox 中测试
在 FireFox 中,您可以从 connectedCallback
访问内部元素。在所有其他浏览器中,您需要 setTimeout
。同一 W3C 标准的不同技术解释。在这种情况下,Apple 工程师是正确的 source。 Chromium 基于相同的引擎。
请注意 C connectedCallback
(或任何方法)中的(延迟)代码如何运行 AFTER disconnectedCallback
.
您需要编写在 DOM 元素不再存在时不会出错的代码。
JSFiddle 操场:https://jsfiddle.net/CustomElementsExamples/n20bwckt/
我一直在尝试为我设计的名为 ws-dialog
的自定义 Web 组件设置属性。它总是在代码上添加一个属性undefined
:
<ws-dialog class="global" undefined="add-page-content"></ws-dialog>
我想在这里做的是声明一个像template
这样的属性,而不是undefined
。这是我用于向所有对话目标元素添加 onclick
事件的代码:
function addDialogEvents(target) {
target.addEventListener("click", () => {
let dialog = document.createElement(Dialog.getName());
let body = document.querySelector("body");
dialog.template = "add-page-content";
body.append(dialog);
});
}
这是我的自定义组件的代码:
"use strict";
class Dialog extends HTMLElement {
connectedCallback() {
//Styles for this custom component are declared in a separate CSS module
}
updateContent(id) {
let content = document.querySelector(`template#${id}`).content;
if (content)
this.append(content);
}
attributeChangedCallback(name, oldValue, newValue) {
this.TEMPLATE = "template";
switch (name) {
case this.TEMPLATE:
this.updateContent(newValue);
break;
}
}
static get observedAttributes() {
return [this.TEMPLATE];
}
static getName() {
return "ws-dialog";
}
get template() {
return this.getAttribute(this.TEMPLATE);
}
set template(template) {
this.setAttribute(this.TEMPLATE, template);
}
}
customElements.define(Dialog.getName(), Dialog);
这里有一个 playground,可以帮助您了解什么时候触发了什么方法。
注意何时 以及调用了多少次 observedAttributes
。
这意味着您的 this.TEMPLATE
是 undefined
,因此成为 Array
undefined
<script>
const log = (...args) => {
let div=document.body.appendChild(document.createElement('DIV'));
div.style = `background:${args.shift()};color:white;font:13px Arial`;
div.append(args.join(" "));
}
customElements.define('my-element', class extends HTMLElement {
log() {
log(this.getAttribute("color"), this.outerHTML.split(">")[0],'>', ...arguments);
}
static get observedAttributes() {
log('red', `my-element observedAttributes`);// NO 'this' / Element here!
return ["color"];
}
constructor() { super().log("constructor") }
connectedCallback() {
this.log("connectedCallback" , this.innerHTML || "No innerHTML" );//FireFox difference!
setTimeout(() => this.log(`delayed connectedCallback ${this.innerHTML}`), 0);
}
attributeChangedCallback(name, oldValue, newValue) { // 4th W3C parameter = Namespace (not implemented in Browsers)
this.log("attributeChangedCallback", name, oldValue || "null", newValue);
}
disconnectedCallback(){ this.log("disconnectedCallback") }
})
document.body.onload = () => {
log('magenta', 'onload event');
A.setAttribute("color", "darkolivegreen");
B.innerHTML = "<my-element id=C color=hotpink>Charlie replaced Bravo</my-element>";
B.remove();
}
</script>
<my-element id=A color=green>Alfa</my-element>
<my-element id=B color=blue>Bravo</my-element>
备注:
有用的图表位于:https://andyogo.github.io/custom-element-reactions-diagram/
仅在 FireFox 中执行顺序略有不同,我的建议是不要开发,仅在 Firefox 中测试
在 FireFox 中,您可以从
connectedCallback
访问内部元素。在所有其他浏览器中,您需要setTimeout
。同一 W3C 标准的不同技术解释。在这种情况下,Apple 工程师是正确的 source。 Chromium 基于相同的引擎。请注意 C
connectedCallback
(或任何方法)中的(延迟)代码如何运行 AFTERdisconnectedCallback
.
您需要编写在 DOM 元素不再存在时不会出错的代码。
JSFiddle 操场:https://jsfiddle.net/CustomElementsExamples/n20bwckt/