在自定义 HTML 元素上定义多个自定义属性
Defining multiple custom attributes on a custom HTML Element
为自定义 HTML 元素的自定义属性添加 getter/setter 非常简单:
customElements.define('custom-el', class extends HTMLElement {
static get observedAttributes() {
return ['customAttr']
}
get customAttr() {
return this.getAttribute('customAttr')
}
set customAttr(value) {
this.setAttribute('customAttr', value)
}
constructor() {
super();
}
})
但是,如果您在同一个元素上有多个自定义属性,这会变得非常麻烦:
customElements.define('custom-el', class extends HTMLElement {
static get observedAttributes() {
return ['customAttr1', 'customAttr2', 'customAttr3']
}
// for attr 1
get customAttr1() {
return this.getAttribute('customAttr1')
}
set customAttr1(value) {
this.setAttribute('customAttr1', value)
}
// for attr 2
get customAttr2() {
return this.getAttribute('customAttr2')
}
set customAttr2(value) {
this.setAttribute('customAttr2', value)
}
// for attr 3
get customAttr3() {
return this.getAttribute('customAttr3')
}
set customAttr3(value) {
this.setAttribute('customAttr3', value)
}
constructor() {
super();
}
})
我一直在考虑如何编写一个函数来从自定义属性名称数组生成 getter/setters,但是如果不能将变量字符串作为get/set.
的名称
documentation for "getter"建议方括号中的表达式是可以接受的,这适用于一个可变字符串:
const x = "customAttr";
customElements.define('custom-el', class extends HTMLElement {
static get observedAttributes() {
return x;
}
get [x]() {
return this.getAttribute(x)
}
set [x](value) {
this.setAttribute(x, value)
}
constructor() {
super();
}
})
<custom-el customAttr="It works"></custom-el>
console.log(document.querySelector("custom-el").customAttr) // yields "It works"
不幸的是,for/forEach 循环在自定义元素定义的主体中是不允许的(在嵌入式子例程之外,此时 get/set 操作不再有效!):
const customAttrs = ["customAttr1", "customAttr2", "customAttr3"];
customElements.define('custom-el', class extends HTMLElement {
static get observedAttributes() {
return customAttrs;
}
customAttrs.forEach( customAttr => {
get [customAttr]() {
return this.getAttribute(customAttr)
}
set [customAttr](value) {
this.setAttribute(customAttr, value)
}
})
constructor() {
super();
}
})
<custom-el customAttr1="It " customAttr2="doesn't " customAttr3="work"></custom-el>
let customEl = document.querySelector("custom-el");
console.log(testEl.customAttr1+testEl.customAttr2+testEl.customAttr3) // yields error
如果自定义 HTMLElement class 有一个像对象的“defineProperty”一样操作的“defineAttribute”方法,你可以这样做:
const customEl = ...
const customAttrs = ["customAttr1", "customAttr2", "customAttr3", ...]
customAttrs.forEach( customAttr => {
HTMLElement.defineAttribute(customEl, customAttr, {
get : function(){ return this.getAttribute(customAttr ); },
set : function(newValue){ this.setAttribute(customAttr, newValue); }
}
}
...但似乎不存在这样的东西。
tl;dr - 在自定义元素上为自定义属性设置多个 setter/getters 真的没有比为每个属性编写 set/get 定义更好的方法了吗?
使用Object.defineProperty( element , attrName , { getter , setter , options} )
将类似的内容添加到您的基类(因此this
是您的自定义元素)
defineProperty(
attr,
getter = (attr) => this.getAttribute(attr),
setter = (val, attr) => (val == undefined ? this.removeAttribute(attr) : this.setAttribute(attr, val)),
options = {
configurable: true,
}
) {
return Object.defineProperty(this, attr, {
get() {
return getter(attr);
},
set(val) {
return setter(val, attr);
},
...options,
});
}
参见:
复数:
为自定义 HTML 元素的自定义属性添加 getter/setter 非常简单:
customElements.define('custom-el', class extends HTMLElement {
static get observedAttributes() {
return ['customAttr']
}
get customAttr() {
return this.getAttribute('customAttr')
}
set customAttr(value) {
this.setAttribute('customAttr', value)
}
constructor() {
super();
}
})
但是,如果您在同一个元素上有多个自定义属性,这会变得非常麻烦:
customElements.define('custom-el', class extends HTMLElement {
static get observedAttributes() {
return ['customAttr1', 'customAttr2', 'customAttr3']
}
// for attr 1
get customAttr1() {
return this.getAttribute('customAttr1')
}
set customAttr1(value) {
this.setAttribute('customAttr1', value)
}
// for attr 2
get customAttr2() {
return this.getAttribute('customAttr2')
}
set customAttr2(value) {
this.setAttribute('customAttr2', value)
}
// for attr 3
get customAttr3() {
return this.getAttribute('customAttr3')
}
set customAttr3(value) {
this.setAttribute('customAttr3', value)
}
constructor() {
super();
}
})
我一直在考虑如何编写一个函数来从自定义属性名称数组生成 getter/setters,但是如果不能将变量字符串作为get/set.
的名称documentation for "getter"建议方括号中的表达式是可以接受的,这适用于一个可变字符串:
const x = "customAttr";
customElements.define('custom-el', class extends HTMLElement {
static get observedAttributes() {
return x;
}
get [x]() {
return this.getAttribute(x)
}
set [x](value) {
this.setAttribute(x, value)
}
constructor() {
super();
}
})
<custom-el customAttr="It works"></custom-el>
console.log(document.querySelector("custom-el").customAttr) // yields "It works"
不幸的是,for/forEach 循环在自定义元素定义的主体中是不允许的(在嵌入式子例程之外,此时 get/set 操作不再有效!):
const customAttrs = ["customAttr1", "customAttr2", "customAttr3"];
customElements.define('custom-el', class extends HTMLElement {
static get observedAttributes() {
return customAttrs;
}
customAttrs.forEach( customAttr => {
get [customAttr]() {
return this.getAttribute(customAttr)
}
set [customAttr](value) {
this.setAttribute(customAttr, value)
}
})
constructor() {
super();
}
})
<custom-el customAttr1="It " customAttr2="doesn't " customAttr3="work"></custom-el>
let customEl = document.querySelector("custom-el");
console.log(testEl.customAttr1+testEl.customAttr2+testEl.customAttr3) // yields error
如果自定义 HTMLElement class 有一个像对象的“defineProperty”一样操作的“defineAttribute”方法,你可以这样做:
const customEl = ...
const customAttrs = ["customAttr1", "customAttr2", "customAttr3", ...]
customAttrs.forEach( customAttr => {
HTMLElement.defineAttribute(customEl, customAttr, {
get : function(){ return this.getAttribute(customAttr ); },
set : function(newValue){ this.setAttribute(customAttr, newValue); }
}
}
...但似乎不存在这样的东西。
tl;dr - 在自定义元素上为自定义属性设置多个 setter/getters 真的没有比为每个属性编写 set/get 定义更好的方法了吗?
使用Object.defineProperty( element , attrName , { getter , setter , options} )
将类似的内容添加到您的基类(因此this
是您的自定义元素)
defineProperty(
attr,
getter = (attr) => this.getAttribute(attr),
setter = (val, attr) => (val == undefined ? this.removeAttribute(attr) : this.setAttribute(attr, val)),
options = {
configurable: true,
}
) {
return Object.defineProperty(this, attr, {
get() {
return getter(attr);
},
set(val) {
return setter(val, attr);
},
...options,
});
}
参见:
复数: