Polymer, соблюдайте глобальный путь, пожалуйста

В Polymer 1.0 вы можете удалить {{localPropFoo.bar}}, а bar будет наблюдаться за изменениями, если вы используете this.set('localPropFoo.bar', 'new value'); для обновления его значения.

Но что делать, если вы хотите привязать шаблон к внешнему объекту, который находится вне вашего контроля? Например, это {{window.globalFoo.bar}} не будет привязано к bar изменениям, потому что внешний код не зависит от Polymer и не вызывает this.set.

Демо на codepen

Использование Object.observe вручную требует дополнительного кода и не работает в FireFox (грязные проверки observe.js для спасение).

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


person ilyaigpetrov    schedule 12.09.2015    source источник
comment
Вы пробовали железные сигналы? Он может прослушивать любое событие iron-signal-* независимо от его местоположения в DOM.   -  person Neil John Ramal    schedule 12.09.2015
comment
Идиоматический способ - не привязываться к внешним объектам, находящимся вне вашего контроля. Используете ли вы другие библиотеки, которые его устанавливают? Если вы контролируете все свое приложение, тогда в нем не должно быть необходимости.   -  person Andrey    schedule 12.09.2015
comment
наблюдать-js - ваш единственный помощник здесь, но это неуклюжий подход   -  person Andrey    schedule 12.09.2015
comment
@ Андрей Я использую свою собственную библиотеку, которую я не хочу зависеть от Polymer, но я могу каким-то образом заставить ее генерировать события, возможно, с помощью Node EventEmitter.   -  person ilyaigpetrov    schedule 12.09.2015
comment
@ilyaigpetrov вы можете использовать нативные события JS   -  person Andrey    schedule 12.09.2015
comment
Вы всегда можете передать изменение с помощью пользовательского события, вот как полимер достичь наблюдать.   -  person wener    schedule 13.09.2015


Ответы (1)


Polymer не делает наблюдение "из коробки", потому что:

  1. Object.observe поддержка не вездесуща, а грязные проверки стоят дорого.
  2. Object.observe может быть дорогим само по себе.

Предполагаемое решение

Отслеживайте изменения самостоятельно, вызывайте notifyPath, this.fire('global-foo-changed', {path: 'globalFoo.bar', value:...}, this.set и this.push.
Все они отправляют соответствующие не всплывающие (захватывающие) globalFoo-changed настраиваемые события (только при необходимости).

Почему мои события global-foo-changed влияют только на элемент this?

  1. global-foo-changed события захватываются (не всплывают).
  2. Полимерные элементы прослушивают всплывающие события по умолчанию.
  3. По какой-то причине эти захватывающие слушатели захватывают события пузырьков, отправленные из одного и того же элемента (а не из его дочерних элементов). Демо на codepen.

Вы можете залатать полимер следующим образом (я не понимаю, как это работает):

SharedGlobalsBehavior = {
  properties: {
    globalFoo: {
      type: Object,
      notify: true,
      value: globalFoo
    }
  },
  created: function() {
    window.addEventListener('global-foo-changed', () => {
      if (!event.detail || !event.detail.path)
        return; // Property initialization.
      this.notifyPath(event.detail.path, event.detail.value);
    },/* if capturing */ true);
  }
};

Почему нет наблюдения из коробки

...иногда императивный код требует прямого изменения подсвойств объекта. Поскольку мы избегаем более сложных механизмов наблюдения, таких как Object.observe или грязная проверка, чтобы добиться наилучшей кросс-платформенной производительности при запуске и выполнении для наиболее распространенных случаев использования, изменение подсвойств объекта напрямую требует сотрудничества со стороны пользователя.

В частности, Polymer предоставляет два метода, которые позволяют уведомлять систему о таких изменениях: notifyPath(путь, значение) и set(путь, значение), где путь — это строка, идентифицирующая путь (относительно элемента хоста).

person ilyaigpetrov    schedule 18.09.2015