使用代理访问自定义元素的数据集

问题描述 投票:4回答:1

想象一下这个简单的自定义元素:

<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吗?

javascript ecmascript-6 custom-element proxies
1个回答
4
投票

创建代理不会改变目标对象,也不会成为代理。代理是一个包裹目标的新对象。在你的代码中,你只是扔掉了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>
© www.soinside.com 2019 - 2024. All rights reserved.