Aurelia 绑定挂钩 "nested" 自定义元素中的数据更新
Aurelia binding hook on "nested" data update in custom element
我想在绑定对象发生更新时收到通知。
这个笨蛋 http://plnkr.co/edit/7thr0V 证明了我的问题。
更详细:
我通过绑定 [data.bind] 将对象 "data" 传递到自定义元素中。如果我现在
更新数据中的 属性,我希望,"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 中,我分两次更新数据对象。
第一个区间每秒编辑一个"nested"属性。
第二个间隔每五秒将数据对象设置为新的。
在第二个间隔,钩子和观察者被调用,
但我想知道第一个间隔何时发生任何变化。
setInterval(() => {
this.data.nested.content += "!";
}, 1000);
setInterval(() => {
this.data = {
nested: {
content: "Hello nested world No. " + this.counter++ + "!"
}
};
}, 5000);
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.
我想在绑定对象发生更新时收到通知。 这个笨蛋 http://plnkr.co/edit/7thr0V 证明了我的问题。
更详细: 我通过绑定 [data.bind] 将对象 "data" 传递到自定义元素中。如果我现在 更新数据中的 属性,我希望,"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 中,我分两次更新数据对象。 第一个区间每秒编辑一个"nested"属性。 第二个间隔每五秒将数据对象设置为新的。 在第二个间隔,钩子和观察者被调用, 但我想知道第一个间隔何时发生任何变化。
setInterval(() => {
this.data.nested.content += "!";
}, 1000);
setInterval(() => {
this.data = {
nested: {
content: "Hello nested world No. " + this.counter++ + "!"
}
};
}, 5000);
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.