【问题标题】:Angular2 version of knockout's computed observableAngular2 版本的淘汰赛计算的 observable
【发布时间】:2016-07-21 19:30:01
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: javascript angular knockout.js computed-observable


    【解决方案1】:

    如果您使用 TypeScript,我会考虑使用 getter。您还可以让您的组件使用 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;
      } 
    }
    

    【讨论】:

    • 这并不能保证当其中一个输入发生变化时函数的内容只有计算机。如果 getter 函数正在执行某种计算密集型工作(例如对大量对象进行排序),这将继续低效。 - 您可以在提供的 plunkr 中看到这一点。
    【解决方案2】:

    最接近ko.observable 的类似物是Subject 甚至BehaviorSubject,对于ko.computed,您可以使用Observable.combineLatest

    这是一个hello world的例子:

    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 管道,您始终可以订阅您的流和它们的组件属性

    【讨论】:

      猜你喜欢
      • 2019-06-02
      • 1970-01-01
      • 2020-05-30
      • 2013-03-22
      • 1970-01-01
      • 2013-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多