Как наблюдать за изменениями подсвойств в Polymer?

Для этого объекта:

obj = {
        a:'a value',
        b:'b value'
      }

Мне нужно вызывать функцию всякий раз, когда изменяется значение a или b. Я видел Наблюдение за изменениями объекта в Polymer JS, но это решение не работает для меня.

Я безуспешно пытался добавить наблюдателя следующим образом:

 observers: [
    'abc(obj.*)' //abc is function which need to be called
 ]

и:

 observe: {
    'obj.a': 'abc'     // here I'm observing a's attribute
 },

Планкер: http://plnkr.co/edit/BvX25wJHJh7i2aeyVBks?p=preview


person ksh    schedule 10.12.2016    source источник


Ответы (1)


В вашем Plunker наблюдатель не вызывается после изменений в obj.a в вашем обратном вызове ready(), потому что подсвойство было назначено напрямую, что не запускает автоматически событие изменения для просмотра наблюдателями (или привязками данных). Вот исправленный плункер.

Документы Polymer описывают, как наблюдать за изменениями подсвойств. :

Чтобы Polymer правильно обнаружил изменение вложенного свойства, вложенное свойство необходимо обновить одним из следующих двух способов:

Есть и третий способ: вызовом notifyPath.

После внесения изменений в this.obj.a вы можете уведомить наблюдателей и обновить привязки, вызвав this.notifyPath('obj.a', this.obj.a):

this.obj.a = 100;
this.obj.a++;
this.notifyPath('obj.a', this.obj.a);

HTMLImports.whenReady(() => {
  Polymer({
    is: 'x-foo',
    properties: {
      obj: {
        type: Object,
        value: () => ({a: 1, b: 2})
      }
    },
    observers: [
      '_objChanged(obj.a, obj.b)'
    ],
    _objChanged: function(a, b) {
      console.log('a', a, 'b', b);
    },
    _doNotifyPath: function() {
      this.obj.a++;
      this.obj.b++;
      this.notifyPath('obj.a', this.obj.a);
      this.notifyPath('obj.b', this.obj.b);
    }
  });
});
<head>
  <base href="https://polygit.org/polymer+1.11.3/components/">
  <script src="webcomponentsjs/webcomponents-lite.js"></script>
  <link rel="import" href="polymer/polymer.html">
</head>
<body>
  <x-foo></x-foo>

  <dom-module id="x-foo">
    <template>
      <div>obj.a = [[obj.a]]</div>
      <div>obj.b = [[obj.b]]</div>
      <button on-tap="_doNotifyPath">Notify Path</button>
    </template>
  </dom-module>
</body>

Кроме того, вы можете объединить настройку и уведомление с this.set('obj.a', 'new value')< /а>:

this.set('obj.a', this.obj.a + 1);

HTMLImports.whenReady(() => {
  Polymer({
    is: 'x-foo',
    properties: {
      obj: {
        type: Object,
        value: () => ({a: 1, b: 2})
      }
    },
    observers: [
      '_objChanged(obj.a, obj.b)'
    ],
    _objChanged: function(a, b) {
      console.log('a', a, 'b', b);
    },
    _doSet: function() {
      this.set('obj.a', this.obj.a + 1);
      this.set('obj.b', this.obj.b + 1);
    }
  });
});
<head>
  <base href="https://polygit.org/polymer+1.11.3/components/">
  <script src="webcomponentsjs/webcomponents-lite.js"></script>
  <link rel="import" href="polymer/polymer.html">
</head>
<body>
  <x-foo></x-foo>

  <dom-module id="x-foo">
    <template>
      <div>obj.a = [[obj.a]]</div>
      <div>obj.b = [[obj.b]]</div>
      <button on-tap="_doSet">Set</button>
    </template>
  </dom-module>
</body>

codepen

person tony19    schedule 10.12.2016
comment
спасибо за ваш ответ, не могли бы вы сказать мне, почему он не вызывает наблюдателя автоматически в моем коде plunker?!! и я только что написал демонстрационный код, в моем исходном коде объект имеет так много атрибутов, и я не могу вызывать эту функцию каждый раз, так как каждый раз может меняться один или несколько объектов, и мне нужно вызывать наблюдателя только один раз!! - person ksh; 10.12.2016
comment
Можно ли использовать подстановочный знак, например (obj.*) ?? - person ksh; 10.12.2016
comment
Я обновил ответ, чтобы явно указать, почему наблюдатель не вызывается в вашем плункере. - person tony19; 10.12.2016
comment
В вашем комментарии кажется, что вы хотите, чтобы наблюдатель срабатывал только один раз (т. е. только первое изменение), что в настоящее время невозможно с общедоступными API-интерфейсами Polymer. Вам придется реализовать свой собственный механизм (например, флаг), чтобы игнорировать последующие изменения. - person tony19; 10.12.2016
comment
В вашем комментарии также указано, что вы хотите наблюдать за всеми подсвойствами obj, используя выражение наблюдателя с подстановочными знаками ((obj.*)). Да, это возможно. Наблюдатель будет вызываться для любых изменений в obj (включая его свойство .length). - person tony19; 10.12.2016
comment
спасибо за объяснение, у меня есть еще одна путаница, если в моем объекте obj предположить, что у меня есть 10 атрибутов, и каждый раз может меняться любое количество подсвойств, поэтому я не могу написать this.notifyPath('obj.a', this. цель а); this.notifyPath('obj.b',this.obj.b); эти 10 раз, потому что он вызывает мою функцию изменения много раз, наконец, мне нужно любое количество подсвойств, которые могут измениться, но мне нужно вызвать функцию изменения только один раз. !! есть ли решение для этого?? - person ksh; 12.12.2016