Angular2版本的淘汰赛的计算可观察量

时间:2016-04-01 20:54:26

标签: javascript angular knockout.js computed-observable

我目前正在努力将我从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

2 个答案:

答案 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管道,您始终可以订阅您的流及其组件属性