我是Web组件的新手,当我用html编写组件并直接在html中添加属性时遇到问题。 问题在于该组件不会触发set属性函数。
仅当我设置属性或使用javascript创建组件并将其添加到DOM时,set属性函数才有效。
我创建了一支笔来举例说明我的问题:
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>
答案 0 :(得分:2)
@connexo对属性发生了什么,如何操作它们以及如何提取它们的值进行了很好的解释。
我想通过稍微改变结构来补充他的解决方案。
字母和setter::使用字母和setter操纵元素上的属性。这样,您可以通过使用article
更改属性值和HTML来更改news-article.article = { title: 'Breaking news' }
属性,并使用news-article.article
获取article
属性的当前值。
因为您正在观察article
属性,所以当您更改attributeChangedCallback
属性值时,它将触发article
。您应该放置逻辑,以更改所有但属性值。根据您的情况,更改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!
答案 1 :(得分:1)
setAttribute
接受两个参数,相反,您将分配 JSON.parse(newVal)
到任何this.setAttribute(attrName)
返回的值(我假设为undefined
)。
this.setAttribute(attrName) = JSON.parse(newVal);
必须
this.setAttribute(attrName, JSON.parse(newVal));
最重要的是,请注意{ title: 'static value' }
是不是有效的JSON。您不能使用单引号将键或值引起来。它必须是双引号。
接下来,出于两个原因,在您的this.setAttribute(attrName, JSON.parse(newVal))
中进行attributeChangedCallback
毫无意义。
attributeChangedCallback
的原因)String
个值。相反,您要做的是
this.article = JSON.parse(newVal);
这将触发您的吸气剂(这正是您想要的,因为那是真正更新您的组件的东西)。
我认为您的误解是由于您假设自定义属性会自动与sanme-name属性进行同步,而情况并非如此。
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() {
return ['article'];
}
constructor() {
super();
this.attachShadow({
mode: 'open'
});
}
set article(val) {
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
border: 3px solid #000;
padding: 15px;
}
h2 {
text-transform: uppercase;
}
</style>
<h2>${val.title}</h2>`;
}
get article() {
return this.getAttribute('article');
}
attributeChangedCallback(attrName, oldVal, newVal) {
this.article = JSON.parse(newVal);
}
}
window.customElements.define('news-article', NewsArticle);
<news-article article='{ "title": "static value" }'></news-article>
<news-article></news-article>
<news-article article='{ "title": "static value" }'></news-article>