我目前正在努力将我从Knockout编写的一些代码移植到Angular2。我真的很喜欢knockout中计算的observable的构造,这意味着只有当obeservable依赖于变化时才计算该函数的结果。
我知道我可以在角度中使用一个函数,它只会在结果发生变化时更新视图(即使它会多次计算结果),但我的计算机正在进行排序,这就是我只想要工作的原因当输入实际改变时要完成。
我发现下面的链接解释了如何使用angularjs,但我不知道如何将其转换为angular2(typescript)
http://www.jomendez.com/2015/02/06/knockoutjs-computed-equivalent-angularjs/ KO.Computed equivalent in Angular / Breeze Initializer
答案 0 :(得分:8)
如果您使用的是TypeScript,我会考虑 getter 。您还可以使Component使用ChangeDetectionStrategy.OnPush来确保仅在其中一个属性发生更改时才评估绑定。这是一个Plunker:https://plnkr.co/edit/PjcgmFCDj8UvBR7wRJs2?p=preview
import {Component,ChangeDetectionStrategy} from 'angular2/core'
@Component({
selector:'person',
template:`<div>
<div>
First Name
<input [(ngModel)]="firstName">
</div>
<div>
Last Name
<input [(ngModel)]="lastName">
</div>
{{fullName}}
</div>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class Person{
firstName = '';
lastName = '';
get fullName(){
return this.firstName + ' ' + this.lastName;
}
}
答案 1 :(得分:3)
ko.observable
最接近的类似物是Subject
甚至是BehaviorSubject
,而对于ko.computed
,您可以使用Observable.combineLatest
这里有一个你好世界的例子:
import 'rxjs/add/operator/map';
import {Component} from '@angular/core';
import {Observable, BehaviorSubject} from "rxjs";
@Component({
selector: 'app-root',
template: `<div>
<button (click)="both()">both</button>
<button (click)="first()">first</button>
<button (click)="last()">last</button>
<button (click)="ageNow()">age</button>
<hr />
fullName: {{fullName | async}}
<hr />
age: {{age | async}}
</div>`
})
export class AppComponent {
firstName = new BehaviorSubject(''); // aka this.firstName = ko.observable('')
lastName = new BehaviorSubject('');
age = new BehaviorSubject(0);
fullName = Observable.combineLatest(this.firstName, this.lastName) // aka this.fullName = ko.computed(...)
.do(values => console.log('computed fired'))
.map(values => values.join(' ').trim());
both() {
this.first();
this.last();
}
first() {
this.firstName.next('foo ' + Date.now());
}
last() {
this.lastName.next('bar ' + Date.now());
}
ageNow() {
this.age.next(Date.now());
}
}
并且你可能想要使用表单,然后示例将是这样的:
import 'rxjs/add/operator/map';
import {Component} from '@angular/core';
import {Observable, BehaviorSubject} from "rxjs";
import {FormGroup, FormControl, FormBuilder} from "@angular/forms";
@Component({
selector: 'app-root',
template: `<form [formGroup]="form">
<input formControlName="firstName" />
<input formControlName="lastName" />
{{fullName | async}}
</form>`
})
export class AppComponent {
form:FormGroup;
firstName = new FormControl('');
lastName = new FormControl('');
fullName = Observable.combineLatest(
this.firstName.valueChanges.startWith(''),
this.lastName.valueChanges.startWith('')
).map(values => values.join(' ').trim());
constructor(private fb:FormBuilder) {
this.form = fb.group({
firstName: this.firstName,
lastName: this.lastName
});
}
}
请注意,在表单示例中,我们不是在观察FormControl,而是在valueChanges
流中构建它,我们也为它定义了初始值。
如果您不希望在模板中处理| async
管道,您始终可以订阅您的流及其组件属性