简体   繁体   English

Aurelia绑定钩子在自定义元素中的“嵌套”数据更新

[英]Aurelia binding hook on “nested” data update in custom element

I'm want to get notified, when a update happened in an binded object. 当绑定对象发生更新时,我想收到通知。 This plunk http://plnkr.co/edit/7thr0V demonstrates my problem. 这个插件http://plnkr.co/edit/7thr0V演示了我的问题。

In more detail: I pass an object "data" via bind [data.bind] into a custom element. 更详细:我通过bind [data.bind]将对象“data”传递给自定义元素。 if i now update a property in data, i would expect, that the "dataChanged" hook in the custom element is called. 如果我现在更新数据中的属性,我希望,调用自定义元素中的“dataChanged”挂钩。 If i show property from the binded data object in the custom elements template, it gets updated, so the binding itself works properly. 如果我在自定义元素模板中显示绑定数据对象的属性,它会更新,因此绑定本身可以正常工作。

My second reproach is using the ObserverLocator, but it doesn't fire on nested updates, too. 我的第二个责备是使用ObserverLocator,但它也不会触发嵌套更新。

The object in app.js: app.js中的对象:

this.data = {
  nested: {
    content: "Hello nested world!"
  }
};

The binding to custom element ce: 绑定到自定义元素ce:

<require from="ce"></require>
<ce data.bind="data"></ce>

The ce.js part: ce.js部分:

@bindable data;

constructor(observerLocator) {
  this.observerLocator = observerLocator;

  var subscription = this.observerLocator
        .getObserver(this, 'data')
        //.getObserver(this, 'data["nested"]["content"]') //Doesn't work
        //.getObserver(this, 'data.nested.content') //Doesn't work
        .subscribe(this.onChangeData);
}

onChangeData(newData, oldData) {
  console.log('data changed from ', oldData, newData);
}

dataChanged(d) {
    console.log("Changed", d);
}

The ce template part: ce模板部分:

${data.nested.content}

In app.js I update the data object in 2 intervals. 在app.js中,我以2个间隔更新数据对象。 The first interval every second edit a "nested" property. 每秒的第一个间隔编辑一个“嵌套”属性。 The second interval every five seconds sets the data object new. 每五秒钟的第二个间隔将数据对象设置为新的。 On the second interval, the hooks and the observer get called, but I want a way to know, when the first intervals did any change. 在第二个间隔,钩子和观察者被调用,但我想知道,当第一个间隔做任何改变时。

setInterval(() => {
  this.data.nested.content += "!";
}, 1000);


setInterval(() => {
  this.data = {
  nested: {
    content: "Hello nested world No. " + this.counter++  + "!"
  }
};
}, 5000);

The ObserverLocator is Aurelia's bare metal API for observing simple property changes and array/map/set mutation. ObserverLocator是Aurelia的裸机API,用于观察简单的属性更改和数组/映射/集变异。

There's a new, higher level API called the BindingEngine that you can use to observe complex expressions. 有一个新的,更高级别的API,称为BindingEngine ,可用于观察复杂的表达式。

Here's an example: https://gist.run?id=868a7611952b2e40f350 这是一个例子: https//gist.run?id = 868a7611952b2e40f350

ce.html ce.html

<template>
  ${data.nested.content}


  <!-- debug logging -->
  <h4>Observed Changes:</h4>
  <div repeat.for="change of changes"><pre><code>${change}</code></pre></div>
</template>

ce.js ce.js

import {
  bindable,
  BindingEngine,
  inject
} from "aurelia-framework";

@inject(BindingEngine)
export class Ce {
  @bindable data;

  changes = []; // debug logging

  constructor(bindingEngine) {
    this.bindingEngine = bindingEngine;
  }

  expressionChanged(newValue, oldValue) {
    // debug logging:
    this.changes.splice(0, 0, `expressionChanged: "${newValue}"`);
  }

  syncSubscription(subscribe) {
    if (this.subscription) {
      this.subscription.dispose();
      this.subscription = null;
    }
    if (subscribe && this.data) {
      let observer = this.bindingEngine.expressionObserver(this.data, 'nested.content');
      this.subscription = observer.subscribe(::this.expressionChanged);
    }
  }

  dataChanged(newValue, oldValue) {
    // subscribe to new data instance
    this.syncSubscription(true);

    // debug logging:
    this.changes.splice(0, 0, `dataChanged: ${JSON.stringify(newValue, null, 2)}`);
  }

  attached() {
    // subscribe
    this.syncSubscription(true);
  }

  detached() {
    // unsubscribe (avoid memory leaks)
    this.syncSubscription(false);
  }
}

Why doesn't aurelia observe whole objects for changes by default? 为什么aurelia默认情况下不会观察整个对象的变化?

It's too expensive in terms of speed and memory to eagerly observe everything. 在速度和记忆力方面过于昂贵,急切地观察一切。 Not all browsers support object.observe. 并非所有浏览器都支持object.observe。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM