使用代理访问自定义元素的数据集
Using a proxy to access the dataset of a custom element
想象一下这个微不足道的自定义元素:
<my-el data-cute-number="7" id="foo"></my-el>
document.getElementById('foo').dataset.cuteNumber
,正如预期的那样,returns 字符串“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>
想象一下这个微不足道的自定义元素:
<my-el data-cute-number="7" id="foo"></my-el>
document.getElementById('foo').dataset.cuteNumber
,正如预期的那样,returns 字符串“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>