4

我目前正在将一些我从 Knockout 编写的代码移植到 Angular2。我真的很喜欢淘汰赛中计算的可观察对象的构造,这意味着该函数的结果仅在它依赖于变化的可观察对象时才计算。

我知道我可以使用角度函数,它只会在结果发生变化时更新视图(即使它会多次计算结果),但我的计算正在进行排序,这就是为什么我只希望完成工作当输入实际发生变化时。

我在下面找到了解释如何使用 angularjs 的链接,但我不确定如何将其转换为 angular2(打字稿)

http://www.jomendez.com/2015/02/06/knockoutjs-computed-equivalent-angularjs/ KO.Computed 等效于 Angular / Breeze Initializer

4

2 回答 2

8

如果您使用 TypeScript,我会考虑使用吸气剂。您还可以让您的组件使用 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;
  } 
}
于 2016-04-01T23:43:54.767 回答
4

ko.observableisSubject或 even最接近的类似物,BehaviorSubjectko.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模板中的管道,您始终可以订阅您的流和它们的组件属性

于 2017-01-23T15:03:48.913 回答