Использование прокси для доступа к набору данных пользовательского элемента - PullRequest
4 голосов
/ 26 марта 2019

Представьте себе этот тривиальный пользовательский элемент:

<my-el data-cute-number="7" id="foo"></my-el>

document.getElementById('foo').dataset.cuteNumber, как и ожидалось, возвращает строку «7». Я хотел бы создать прокси-сервер для доступа к свойствам набора данных, который выполняет приведение к Number для меня, потому что я использую свойство alot в коде компонента и хотел бы избегать многократного приведения его вручную при каждом обращении к нему. Я также не хочу создавать дополнительный метод получения для нового свойства (например, get cuteNumber() { return Number(this.dataset.cuteNumber); }) на самом компоненте, так как тогда мне придется выполнять всю синхронизацию вручную (так как мне также потребуется установщик), убедитесь, что я избегаю бесконечные циклы обновления и т. д.

Как я понимаю, прокси, именно здесь мне поможет прокси.

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 элемента?

1 Ответ

4 голосов
/ 26 марта 2019

Создание прокси не изменяет целевой объект, оно не становится прокси.Прокси - это новый объект, который оборачивается вокруг цели.В своем коде вы просто отбрасываете 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>
...