简体   繁体   中英

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

I'm using angular 2. I have a component with an input. I want to be able to write some code when the input value changes. The binding is working, and if the data is changed (from outside the component) I can see that there is change in the 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...
    }
}

You could use the lifecycle hook 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...
  }
}

This hook is triggered when:

if any bindings have changed

See these links for more details:

As mentioned in the comments of Thierry Templier's answer , ngOnChanges lifecycle hook can only detect changes to primitives. I found that by using ngDoCheck instead, you are able to check the state of the object manually to determine if the object's members have changed:

A full Plunker can be found here . But here's the important part:

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();
        }
    }

It should be noted that the Angular documentation provides this caution about using ngDoCheck :

While the ngDoCheck hook can detect when the hero's name has changed, it has a frightful cost. This hook is called with enormous frequency — after every change detection cycle no matter where the change occurred. It's called over twenty times in this example before the user can do anything.

Most of these initial checks are triggered by Angular's first rendering of unrelated data elsewhere on the page. Mere mousing into another input box triggers a call. Relatively few calls reveal actual changes to pertinent data. Clearly our implementation must be very lightweight or the user experience will suffer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM