自定义元素既是DOM 实体又是JavaScript 对象,因此两者之间应该同步变化。换句话说,对DOM
的修改应该反映到JavaScript 对象,反之亦然。要从JavaScript 对象反射到DOM,常见的方式是使用获
取函数和设置函数。下面的例子演示了在JavaScript 对象和DOM 之间反射bar 属性的过程:
document.body.innerHTML = <x-foo></x-foo>
;
class FooElement extends HTMLElement {
constructor() {
super();
this.bar = true;
}
get bar() {
return this.getAttribute(‘bar’);
}
set bar(value) {
this.setAttribute(‘bar’, value)
}
}
customElements.define(‘x-foo’, FooElement);
console.log(document.body.innerHTML);
//
另一个方向的反射(从DOM 到JavaScript 对象)需要给相应的属性添加监听器。为此,可以使用
observedAttributes()获取函数让自定义元素的属性值每次改变时都调用attributeChanged-
Callback():
class FooElement extends HTMLElement {
static get observedAttributes() {
// 返回应该触发attributeChangedCallback()执行的属性
return [‘bar’];
}
get bar() {
return this.getAttribute(‘bar’);
}
set bar(value) {
this.setAttribute(‘bar’, value)
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
console.log(${oldValue} -> ${newValue}
);
this[name] = newValue;
}
}
}
customElements.define(‘x-foo’, FooElement);
document.body.innerHTML = <x-foo bar="false"></x-foo>
;
// null -> false
document.querySelector(‘x-foo’).setAttribute(‘bar’, true);
// false -> true
升级自定义元素
并非始终可以先定义自定义元素,然后再在DOM 中使用相应的元素标签。为解决这个先后次序问
题,Web 组件在CustomElementRegistry 上额外暴露了一些方法。这些方法可以用来检测自定义元
素是否定义完成,然后可以用它来升级已有元素。
如果自定义元素已经有定义,那么CustomElementRegistry.get()方法会返回相应自定义元素
的类。类似地,CustomElementRegistry.whenDefined()方法会返回一个期约,当相应自定义元素
有定义之后解决:
customElements.whenDefined(‘x-foo’).then(() => console.log(‘defined!’));
console.log(customElements.get(‘x-foo’));
// undefined
customElements.define(‘x-foo’, class {});
// defined!
console.log(customElements.get(‘x-foo’));
// class FooElement {}
连接到DOM的元素在自定义元素有定义时会自动升级。如果想在元素连接到DOM 之前强制升级,
可以使用CustomElementRegistry.upgrade()方法:
// 在自定义元素有定义之前会创建HTMLUnknownElement 对象
const fooElement = document.createElement(‘x-foo’);
// 创建自定义元素
class FooElement extends HTMLElement {}
customElements.define(‘x-foo’, FooElement);
console.log(fooElement instanceof FooElement); // false
// 强制升级
customElements.upgrade(fooElement);
console.log(fooElement instanceof FooElement); // true
javascript七基础学习系列一千六百八十九:反射自定义元素属性
最新推荐文章于 2024-09-09 09:35:48 发布