Aurelia 有 AngularJS $watch 替代品吗?
Does Aurelia have an AngularJS $watch alternative?
我正在尝试将我当前的 Angular.js 项目迁移到 Aurelia.js。
我正在尝试做类似的事情:
report.js
export class Report {
list = [];
//TODO
listChanged(newList, oldList){
enter code here
}
}
report.html
<template>
<require from="component"></require>
<component list.bind="list"></component>
</template>
那么问题来了:如何检测列表何时发生变化?
在Angular.js我能做到
$scope.$watchCollection('list', (newVal, oldVal)=>{ my code });
也许 Aurelia 有类似的东西?
对于 @bindable
字段,只要更新 list
值,就会调用 listChanged(newValue, oldValue)
。请看一下Aurelia docs
@customAttribute('if')
@templateController
export class If {
constructor(viewFactory, viewSlot){
//
}
valueChanged(newValue, oldValue){
//
}
}
您也可以使用 ObserveLocator
,如 Aurelia 作者的博文 here:
中所述
import {ObserverLocator} from 'aurelia-binding'; // or 'aurelia-framework'
@inject(ObserverLocator)
class Foo {
constructor(observerLocator) {
// the property we'll observe:
this.bar = 'baz';
// subscribe to the "bar" property's changes:
var subscription = this.observerLocator
.getObserver(this, 'bar')
.subscribe(this.onChange);
}
onChange(newValue, oldValue) {
alert(`bar changed from ${oldValue} to ${newValue}`);
}
}
UPD
正如 Jeremy Danyow 在 中提到的:
The ObserverLocator is Aurelia's internal "bare metal" API. There's now a public API for the binding engine that could be used:
import {BindingEngine} from 'aurelia-binding'; // or from 'aurelia-framework'
@inject(BindingEngine)
export class ViewModel {
constructor(bindingEngine) {
this.obj = { foo: 'bar' };
// subscribe
let subscription = bindingEngine.propertyObserver(this.obj, 'foo')
.subscribe((newValue, oldValue) => console.log(newValue));
// unsubscribe
subscription.dispose();
}
}
最好的问候,亚历山大
目前看来更好的解决方案是CustomeEvent
完整的解决方案应该是这样的
report.html
<template>
<require from="component"></require>
<component list.bind="list" change.trigger="listChanged($event)"></component>
</template>
component.js
@inject(Element)
export class ComponentCustomElement {
@bindable list = [];
//TODO invoke when you change the list
listArrayChanged() {
let e = new CustomEvent('change', {
detail: this.lis
});
this.element.dispatchEvent(e);
}
}
你必须改变组件元素,添加一些触发函数来改变你的事件。我想该组件知道列表何时更改。
您的原始代码只需稍作调整即可使用:
report.js
import {bindable} from 'aurelia-framework'; // or 'aurelia-binding'
export class Report {
@bindable list; // decorate the list property with "bindable"
// Aurelia will call this automatically
listChanged(newList, oldList){
enter code here
}
}
report.html
<template>
<require from="component"></require>
<component list.bind="list"></component>
</template>
Aurelia 有一个约定,它会在您的视图模型上查找 [propertyName]Changed
方法并自动调用它。此约定用于所有用 @bindable
修饰的属性。更多信息 here
我正在尝试将我当前的 Angular.js 项目迁移到 Aurelia.js。 我正在尝试做类似的事情:
report.js
export class Report {
list = [];
//TODO
listChanged(newList, oldList){
enter code here
}
}
report.html
<template>
<require from="component"></require>
<component list.bind="list"></component>
</template>
那么问题来了:如何检测列表何时发生变化?
在Angular.js我能做到
$scope.$watchCollection('list', (newVal, oldVal)=>{ my code });
也许 Aurelia 有类似的东西?
对于 @bindable
字段,只要更新 list
值,就会调用 listChanged(newValue, oldValue)
。请看一下Aurelia docs
@customAttribute('if')
@templateController
export class If {
constructor(viewFactory, viewSlot){
//
}
valueChanged(newValue, oldValue){
//
}
}
您也可以使用 ObserveLocator
,如 Aurelia 作者的博文 here:
import {ObserverLocator} from 'aurelia-binding'; // or 'aurelia-framework'
@inject(ObserverLocator)
class Foo {
constructor(observerLocator) {
// the property we'll observe:
this.bar = 'baz';
// subscribe to the "bar" property's changes:
var subscription = this.observerLocator
.getObserver(this, 'bar')
.subscribe(this.onChange);
}
onChange(newValue, oldValue) {
alert(`bar changed from ${oldValue} to ${newValue}`);
}
}
UPD
正如 Jeremy Danyow 在
The ObserverLocator is Aurelia's internal "bare metal" API. There's now a public API for the binding engine that could be used:
import {BindingEngine} from 'aurelia-binding'; // or from 'aurelia-framework'
@inject(BindingEngine)
export class ViewModel {
constructor(bindingEngine) {
this.obj = { foo: 'bar' };
// subscribe
let subscription = bindingEngine.propertyObserver(this.obj, 'foo')
.subscribe((newValue, oldValue) => console.log(newValue));
// unsubscribe
subscription.dispose();
}
}
最好的问候,亚历山大
目前看来更好的解决方案是CustomeEvent
完整的解决方案应该是这样的
report.html
<template>
<require from="component"></require>
<component list.bind="list" change.trigger="listChanged($event)"></component>
</template>
component.js
@inject(Element)
export class ComponentCustomElement {
@bindable list = [];
//TODO invoke when you change the list
listArrayChanged() {
let e = new CustomEvent('change', {
detail: this.lis
});
this.element.dispatchEvent(e);
}
}
你必须改变组件元素,添加一些触发函数来改变你的事件。我想该组件知道列表何时更改。
您的原始代码只需稍作调整即可使用:
report.js
import {bindable} from 'aurelia-framework'; // or 'aurelia-binding'
export class Report {
@bindable list; // decorate the list property with "bindable"
// Aurelia will call this automatically
listChanged(newList, oldList){
enter code here
}
}
report.html
<template>
<require from="component"></require>
<component list.bind="list"></component>
</template>
Aurelia 有一个约定,它会在您的视图模型上查找 [propertyName]Changed
方法并自动调用它。此约定用于所有用 @bindable
修饰的属性。更多信息 here