Если мы выполним поиск привязки данных JavaScript, мы найдем результаты, касающиеся структур DOM, некоторые статьи, связанные с устаревшим предложением Object.observe, некоторые примеры, основанные на устаревшем DOM Mutation события , или попытка перенести нестандартный Object.prototype.watch в другие браузеры.

Есть и несколько правильных попыток упростить эту задачу, все они отличаются друг от друга из-за нестандартного способа выполнения такой операции.

Что вообще такое привязка данных?

Хороший вопрос. Нам необходимо понять проблему, прежде чем решить, можем ли мы ее решить и как это сделать.

Стандартного способа нет ... но ...

В течение этих лет были разные попытки дать разработчикам способ реагировать на изменения свойств, и большинство из них терпели неудачу, не поддерживались или становились проблематичными с точки зрения производительности.

В настоящее время существует 2 совершенно разных API, которые дают нам контроль над изменением атрибутов в узлах DOM: Mutation Observer и Custom Elements attributeChangedCallback.

В то время как первый очень мощный и способен наблюдать гораздо больше, чем просто изменения атрибутов, Custom Elements attributeChangedCallbackmethod имеет ту же сигнатуру, что и старый добрый Gecko'sObject.prototype.watchcallback.

(propName, oldVal, newVal) = ›прибыль;

Теоретически это так просто: мы наблюдаем за свойством, и нам нужно заранее знать, какое имя у него есть, и всякий раз, когда оно изменяется, мы сможем отреагировать.

Несмотря на некоторую попытку внедрить {}.watch(prop, callback) в каждый движок, этот старый добрый метод Firefox не будет работать должным образом для узлов DOM с унаследованными аксессорами, как и для всех входных value, checked или disabled специальных атрибутов. Кроме того, привязка настраиваемого средства доступа к объекту означает, что его можно удалить с помощью delete obj.prop, и часы исчезнут с такой операцией.

TL; DR Object.prototype.watch - это не путь

Собственные встроенные модули CustomElements недоступны

Даже следуя самым современным стандартным практикам, мы не сможем перехватить изменения на любом вводе с помощью Custom Elements и его утилиты для отслеживания свойств, по какой-то причине называемых ObservableAttributes.

static get observedAttributes() { return ["value"]; }

TL; DR attributeChangedCallback не масштабируется

Собираем факты для решения

Давайте резюмируем то, что мы узнали и узнали за эти дни:

  • Object.prototype.watch несовместим с узлами DOM, не реализован в JS-движках, не может быть полифилен
  • Пользовательские элементы attributeChangedCallback сохранили ту же сигнатуру, что указывает на то, что этого действительно достаточно / все, что нам нужно, чтобы иметь дело с изменениями свойств.
  • все остальное намного мощнее / слишком сложно для наших нужд

Подводя итог, мы ищем функцию watch()like, которая предоставляет следующее:

  • он должен работать с любым объектом DOM и JS, но загрязнение Object.prototype не является вариантом
  • он не должен нарушать унаследованные функции доступа, такие как входные
  • он должен предотвращать двойной вызов одного и того же обратного вызова, если новое значение точно такое же, как и предыдущее, упрощая двусторонние привязки
  • он должен работать на как можно большем количестве платформ
  • последнее, но не менее важное: он должен быть таким же простым, как {}.watch()

Встречайте wrist .watch (🕗)

Используя стандартную сигнатуру, присутствующую как в .watch(prop,old,new), так и в attributeChangedCallback(attr,old,new) для обратного вызова, и сохраняя целевой объект как thiscontext, wrist является менее 1 КБ утилитой с почти отсутствующей кривой обучения.

Это буквально все. Вы либо наблюдаете, либо отключаете отслеживание общего свойства, которое никогда не переопределяет собственное или унаследованное поведение, а просто перехватывает назначения.

Итак, как бы мы могли решить проблему исходного объекта сообщения ← → входные данные?

Вы можете поиграть вживую, используя postobject в консоли, или протестировать двухстороннюю привязку данных между двумя входами и глобальным объектом.

Резюме с возможными F.A.Q

  • часы синхронны? да, значит, это атрибут Custom Elements ChangedCallback и Object.prototype.watch. Вы, конечно, можете отложить несколько вызовов для одного и того же свойства, если считаете, что это проблема, но наличия свойств, защищенных значением, уже должно быть достаточно для сохранения производительности.
  • может ли свойство иметь несколько наблюдателей? да.
  • какой браузер совместим? скорее всего, любой браузер, поддерживающий базовые функции ES5. Скоро я создам полный список протестированных браузеров, настольных и мобильных.
  • какой-то конкретный нюанс? Если у объекта есть ненастраиваемое свойство, его невозможно просмотреть. Убедитесь, что вам принадлежат объекты, за которыми вы хотите смотреть, или что за такими объектами следует следить. Если свойство удалено, наблюдатель будет потерян, так как его метод доступа также будет потерян. Ни в коем случае не должно быть утечек памяти.

Конец.