Global events ([removed]) didn't change the lo

2019-07-29 14:44发布

问题:

Global events (window.onresize) didn't change the local variable's value.

export class TestComponent implements OnInit {
    a: number = 0;
    b: number = 0;
    ngOnInit() {
        window.onresize = () => {
            this.a = 10;
            this.b = 10;
        };
    }
}

回答1:

Bind to global events using host binding (this is mentioned in the API docs, deep inside the DirectiveMetadata page):

@Component({
  selector: 'my-app',
  template: `<p>Resize window and look at console log.
    <p>{{a}} {{b}}`
})
export class AppComponent {
  @HostListener('window:resize') onResize() {
    this.a++;
    this.b++;
    console.log(this.a, this.b, event)
  }
}

plunker

Your original code does not work because you monkey-patched the onresize handler (that Angular had originally monkey-patched) to your own function. So, Angular no longer has a way to run change detection after the event handler finishes. Using host binding keeps the Angular monkey-patch in place, hence it does not disable change detection, hence your view will update after the resize event fires.



回答2:

didn't change the local variable's value

From your screenshot I can see that this.b = 10 so it did change the variable value.

In the picture you also see a: number = 0. That is just the value of a since the last breakpoint. You can see this.a is also 10



回答3:

I just solved a similar problem by forcing the update code to run in the Angular Zone. The documentation I followed is at https://angular.io/docs/js/latest/api/core/index/DirectiveMetadata-class.html (current as of today 10/8/16).

Something like this should work:

import {Component, OnInit, NgZone} from '@angular/core';

constructor(private _ngZone: NgZone) {
}

ngOnInit() {
    window.onresize = () => {
        this._ngZone.run(() => {
            this.a = 10;
            this.b = 10;
        }
    };
}

This is simpler than Mark Rajcok's answer in this question, however NG2 is still a moving target so no doubt what I have written is one of the improvements that have been made (eg. the link to DirectiveMetadata no longer exists).