想象一下这个简单的自定义元素:
<my-el data-cute-number="7" id="foo"></my-el>
正如预期的那样,document.getElementById('foo').dataset.cuteNumber
返回字符串“7”。我想创建一个代理来访问数据集属性,为我执行转换为Number
,因为我在组件代码中使用了很多属性,并希望每次访问时都不必反复手动转换它。我也不想为组件本身的新属性(例如get cuteNumber() { return Number(this.dataset.cuteNumber); }
)创建额外的getter,因为我必须手动完成所有同步(因为我还需要一个setter),请确保我避免无限更新循环等
据我了解代理,这正是代理将帮助我的地方。
customElements.define('my-el', class extends HTMLElement {
constructor() {
super();
const proxy = new Proxy(this.dataset, {
get: function(context, prop, receiver) {
console.log(`Proxy getter executing for ${prop}`);
switch (prop) {
case 'cuteNumber':
return Number(context[prop]);
break;
default:
return context[prop];
}
}
});
}
})
console.log(typeof document.getElementById('foo').dataset.cuteNumber);
<my-el data-cute-number="7" id="foo"></my-el>
这就是我被困住的地方。
访问dataset
目前不会触发代理(内部console.log
不显示)。
谁能指出我正确的方向?甚至可以代理元素的dataset
吗?
创建代理不会改变目标对象,也不会成为代理。代理是一个包裹目标的新对象。在你的代码中,你只是扔掉了proxy
并且从不使用它 - .dataset
属性不受影响。您要覆盖它或创建新属性:
customElements.define('my-el', class extends HTMLElement {
get dataset() {
//^^^^^^^^^^^^^
return new Proxy(super.dataset, {
// ^^^^^^
get: function(target, prop, receiver) {
console.log(`Proxy getter executing for ${prop}`);
if (prop == 'cuteNumber')
return Number(target.cuteNumber);
return Reflect.get(target, prop, receiver);
}
});
}
});
console.log(typeof document.getElementById('foo').dataset.cuteNumber);
<my-el data-cute-number="7" id="foo"></my-el>
customElements.define('my-el', class extends HTMLElement {
constructor() {
super();
this.numberdata = new Proxy(this.dataset, {
// ^^^^^^^^^^^^^^^^^
get: function(target, prop, receiver) {
return Number(target[prop]);
}
});
}
});
console.log(typeof document.getElementById('foo').numberdata.cuteNumber);
<my-el data-cute-number="7" id="foo"></my-el>