假设我有一个 Web 组件:
customElements.define("custom-list", class CustomList extends HTMLElement {
get filter() {
console.log("get filter");
return this.getAttribute("filter");
}
set filter(value) {
console.log("set filter");
this.setAttribute("filter", value);
}
});
我想使用 setter 方法进行一些初始属性验证,但从未调用过 setter。我尝试通过 HTML 设置属性:
<custom-list filter="some value"></custom-list>
只有当我使用 JavaScript 以编程方式设置属性时,setter 才会被调用:
var list = document.querySelector("custom-list");
list.filter = "some value";
list.setAttribute("filter", "some value"); // DOESN'T WORK EITHER
因此,似乎通过 HTML 设置属性或使用 setAttribute
不会触发 setter,我部分可以理解。我的问题是:
- 只有当我想以编程方式设置属性时才需要 setter 吗?
- 如何对属性进行初始验证?在
connectedCallback
中?假设我只想接受某个字符串,我该如何检测? - 既然属性
filter
无论如何都会被填充,如果我不使用 JavaScript 来设置我的属性,我还需要 setter 吗?
最佳答案
getter 和 setter 是一种定义属性的方式,允许您的代码接收和返回字符串以外的值。
元素的属性总是字符串值。您可以通过解析值来模拟属性中的非字符串。但它们总是作为字符串设置并作为字符串读回。
如果您希望在属性更改时运行代码,则需要添加 attributeChangedCallback
函数并在 observedAttributes
静态 getter 中指明您正在观察的属性。
可以通过调用 setAttribute
和 removeAttribute
在 JavaScript 中设置属性。当浏览器由于页面加载或设置 innerHTML
解析您的 HTML 时,也会设置它们。但即便如此,浏览器也不会设置这些,直到浏览器调用构造函数后,浏览器最终在后台调用 setAttribute
。
customElements.define("custom-list", class CustomList extends HTMLElement {
static get observedAttributes() { return ['filter']; }
constructor() {
super();
this._filter = null; // Save the initial value
}
attributeChangedCallback(attr, oldVal, newVal) {
if (oldVal != newVal) {
// Only set this value if it is different
this.filter = newVal; // Call the setter
}
}
get filter() {
console.log("get filter");
return this._filter; // Return the internal value
}
set filter(value) {
// Only run this if the new value is different from the internal value
if (value !== this._filter) {
console.log(`set filter ${value}`);
this._filter = value; // Set the internal value
this.textContent = value;
// If you want the filter property to always show
// in the attributes then do this:
if (value !== null) {
this.setAttribute('filter', value);
} else {
this.removeAttribute('filter');
}
}
}
});
const el = document.querySelector('custom-list');
setTimeout(() => {
el.filter = 'happy';
}, 2000);
<custom-list filter="10"></custom-list>
始终检查函数attributeChangedCallback
中的oldVal
和newVal
是否不同。否则你可能会陷入无限循环。
还建议您在 setter 中检查不同的值。 同样,避免陷入无限循环。
Setter 还允许您获取特定的数据类型。例如,您可以检查 value
的值是否为数字,如果不是,则抛出一个 TypeError
。或者您只是将传入的值转换为正确的类型。
Setter 还允许您确保一个值是有效的。也许它必须是正数或三个可能的字符串之一。如果不是,您可以抛出一个 RangeError
。
但您必须记住,属性始终是字符串,属性可以是任何内容。
关于javascript - Web 组件 : setter not being called,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56547019/