如何侦听 Angular 2 中代码的变化

how can I listen to changes in code in angular 2?

本文关键字:代码 变化 何侦听 Angular      更新时间:2023-09-26

我正在使用角度2。我有一个带有输入的组件。我希望能够在输入值更改时编写一些代码。绑定正在工作,如果数据被更改(从组件外部),我可以看到 dom 发生了变化。

@Component({
    selector: 'test'
})
@View({
    template: `
    <div>data.somevalue={{data.somevalue}}</div>`
})
export class MyComponent {
    _data: Data;
    @Input()
    set data(value: Data) {
        this.data = value;
    }
    get data() {
        return this._data;
    }
    constructor() {
    }
    dataChagedListener(param) {
        // listen to changes of _data object and do something...
    }
}

您可以使用生命周期钩子ngOnChanges

export class MyComponent {
  _data: Data;
  @Input()
  set data(value: Data) {
    this.data = value;
  }
  get data() {
    return this._data;
  }
  constructor() {
  }
  ngOnChanges([propName: string]: SimpleChange) {
    // listen to changes of _data object and do something...
  }
}

在以下情况下触发此挂钩:

如果任何绑定已更改

有关更多详细信息,请参阅以下链接:

  • https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html
  • https://angular.io/docs/ts/latest/api/core/OnChanges-interface.html

正如 Thierry Templier 的答案评论中提到的,ngOnChanges生命周期钩子只能检测对原语的更改。我发现通过使用ngDoCheck,您可以手动检查对象的状态以确定对象的成员是否已更改:

完整的Plunker可以在这里找到。但这是重要的部分:

import { Component, Input } from '@angular/core';
@Component({
    selector: 'listener',
    template: `
        <div style="background-color:#f2f2f2">
            <h3>Listener</h3>
            <p>{{primitive}}</p>
            <p>{{objectOne.foo}}</p>
            <p>{{objectTwo.foo.bar}}</p>
            <ul>
                <li *ngFor="let item of log">{{item}}</li>
            </ul>
        </div>
    `
})
export class ListenerComponent {
    @Input() protected primitive;
    @Input() protected objectOne;
    @Input() protected objectTwo;
    protected currentPrimitive;
    protected currentObjectOne;
    protected currentObjectTwo;
    protected log = ['Started'];
    ngOnInit() {
        this.getCurrentObjectState();
    }
    getCurrentObjectState() {
        this.currentPrimitive = this.primitive;
        this.currentObjectOne = _.clone(this.objectOne);
        this.currentObjectTwoJSON = JSON.stringify(this.objectTwo);
    }
    ngOnChanges() {
        this.log.push('OnChages Fired.')
    }
    ngDoCheck() {
        this.log.push('DoCheck Fired.');
        if (!_.isEqual(this.currentPrimitive, this.primitive)){
            this.log.push('A change in Primitive''s state has occurred:');
            this.log.push('Primitive''s new value:' + this.primitive);
        }
        if(!_.isEqual(this.currentObjectOne, this.objectOne)){
            this.log.push('A change in objectOne''s state has occurred:');
            this.log.push('objectOne.foo''s new value:' + this.objectOne.foo);
        }
        if(this.currentObjectTwoJSON != JSON.stringify(this.objectTwo)){
            this.log.push('A change in objectTwo''s state has occurred:');
            this.log.push('objectTwo.foo.bar''s new value:' + this.objectTwo.foo.bar);
        }
        if(!_.isEqual(this.currentPrimitive, this.primitive) || !_.isEqual(this.currentObjectOne, this.objectOne) || this.currentObjectTwoJSON != JSON.stringify(this.objectTwo)) {
             this.getCurrentObjectState();
        }
    }

应该注意的是,Angular 文档提供了有关使用 ngDoCheck 的警告:

虽然 ngDoCheck 钩子可以检测英雄的名字何时更改, 它有一个可怕的成本。这个钩子的调用频率很高—— 在每个更改检测周期之后,无论更改在哪里 发生。在此示例中,它在 用户可以做任何事情。

这些初始检查中的大多数是由Angular的第一个触发的。 在页面上的其他位置呈现不相关的数据。仅仅将鼠标拖入 另一个输入框触发呼叫。相对较少的呼叫显示实际 对相关数据的更改。显然,我们的实施必须非常 轻量级或用户体验将受到影响。