【问题标题】:Aurelia binding hook on "nested" data update in custom element自定义元素中“嵌套”数据更新的 Aurelia 绑定挂钩
【发布时间】:2015-11-02 14:49:55
【问题描述】:

我想在绑定对象中发生更新时收到通知。 这个笨拙的http://plnkr.co/edit/7thr0V 说明了我的问题。

更详细: 我通过绑定 [data.bind] 将对象“数据”传递到自定义元素中。如果我现在 我希望更新数据中的属性,即“dataChanged”挂钩 自定义元素被调用。 如果我在自定义元素模板中显示绑定数据对象的属性,它会被更新,因此绑定本身可以正常工作。

我的第二个指责是使用 ObserverLocator,但它也不会在嵌套更新时触发。

app.js 中的对象:

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

与自定义元素 ce 的绑定:

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

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);
}

ce模板部分:

${data.nested.content}

在 app.js 中,我以 2 个间隔更新数据对象。 第一个间隔每隔一秒编辑一个“嵌套”属性。 每五秒的第二个间隔将数据对象设置为新的。 在第二个间隔,钩子和观察者被调用, 但我想知道第一个间隔何时发生任何变化。

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


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

【问题讨论】:

    标签: javascript binding aurelia


    【解决方案1】:

    ObserverLocator 是 Aurelia 的裸机 API,用于观察简单的属性变化和 array/map/set 突变。

    有一个新的更高级别的 API,称为 BindingEngine,您可以使用它来观察复杂的表达式。

    这是一个例子:https://gist.run?id=868a7611952b2e40f350

    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

    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);
      }
    }
    

    为什么 aurelia 默认不观察整个对象的变化?

    就速度和内存而言,急切地观察一切都太昂贵了。并非所有浏览器都支持 object.observe。

    【讨论】:

    • 谢谢!像魅力一样工作 =)
    • 有没有办法获取对整个对象的引用,而不仅仅是旧值和新值?
    猜你喜欢
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    相关资源
    最近更新 更多