我是 Web 组件的新手,当我用 html 编写组件并直接在 html 中添加属性时遇到问题。 问题是组件没有触发设置属性函数。
仅当我设置属性或使用 javascript 创建组件并将其添加到 DOM 时,设置属性函数才有效。
我创建了一支笔来举例说明我的问题:
window.addEventListener('load', () => {
document.body.getElementsByTagName('news-article')[1].article = {
title: 'dynamic value'
};
let element = document.createElement('news-article');
element.article = {
'title': 'dynamic element'
};
document.body.appendChild(element);
})
class NewsArticle extends HTMLElement {
static get observedAttributes() {
debugger
return ['article'];
}
constructor() {
debugger
super();
this.root = this.attachShadow({
mode: 'open'
});
}
set article(val) {
debugger
this.root.innerHTML = `
<style>
:host {
display: block;
border: 3px solid #000;
padding: 15px;
}
h2 {
text-transform: uppercase;
}
</style>
<h2>${val.title}</h2>
`;
}
get article() {
debugger
return this.getAttribute('article');
}
attributeChangedCallback(attrName, oldVal, newVal) {
debugger
this.setAttribute(attrName) = JSON.parse(newVal);
}
}
window.customElements.define('news-article', NewsArticle);
<news-article article="{ title: 'static value' }"></news-article>
<news-article></news-article>
最佳答案
@connexo 对属性发生了什么、如何操纵它们以及如何提取它们的值给出了很好的解释。
我想通过稍微改变结构来添加他的解决方案。
Getters 和 setters:使用 getters 和 setters 来操作元素的属性。这样,您可以通过使用 news-article.article = { title: 'Breaking news' }
更改属性值和 HTML 来更改 article
属性,并使用 news-article.article
获取 article
属性的当前值。
因为您正在观察 article
属性,当您更改 article
属性值时,它将触发 attributeChangedCallback
。你应该把你的逻辑放在那里改变一切但属性的值。在您的情况下,更改 Shadow DOM 的 innerHTML
。
class NewsArticle extends HTMLElement {
/**
* Fire the attributeChangedCallback when the article
* attribute has been changed.
*/
static get observedAttributes() {
return ['article'];
}
constructor() {
super();
this.attachShadow({
mode: 'open'
});
}
/**
* Set the article attribute value.
*
* This will fire the attributeChangedCallback because
* 'article' is in the observedAttributes array.
*/
set article(val) {
this.setAttribute('article', JSON.stringify(val));
}
/**
* Gets the current article attribute value.
*/
get article() {
return JSON.parse(this.getAttribute('article'));
}
/**
* Do something when an attribute is changed.
*
* In this case change the innerHTML of the shadowRoot
* when the 'article' attribute has changed.
*/
attributeChangedCallback(attrName, oldVal, newVal) {
if (attrName === 'article') {
const { title } = JSON.parse(newVal);
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
border: 3px solid #000;
padding: 15px;
}
h2 {
text-transform: uppercase;
}
</style>
<h2>${title}</h2>`;
}
}
}
感谢@connexo 的出色工作!
关于javascript - 自定义元素 : attribute won't update component state,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57543618/