简体   繁体   English

Angular2 / TypeScript-变量未更改

[英]Angular2 / TypeScript - Variable not changed

It looks my variable's isInfinitiveScrollLoaderEnabled value does not change when reaching bottom of page. 看起来我的变量的isInfinitiveScrollLoaderEnabled值在到达页面底部时不会更改。 If I put it at the beginning ngOnInit method, it changes successfully. 如果将其放在ngOnInit方法的开头,则更改成功。

What could be wrong? 有什么事吗

export class SomeClass {
  private isInfinitiveScrollLoaderEnabled: boolean;

  constructor() {
    this.isInfinitiveScrollLoaderEnabled = false;
  }

  ngOnInit() {
    window.onscroll = (event) => {
      if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
        console.log('Bottom of page');
        this.isInfinitiveScrollLoaderEnabled = true;
      }
    };
  }
}

You need leverage the NgZone class to execute the onscroll callback in the context of Angular2 when the event is triggered: 触发事件时,您需要利用NgZone类在NgZone的上下文中执行onscroll回调:

export class SomeClass {
  private isInfinitiveScrollLoaderEnabled: boolean;

  constructor(private ngZone: NgZone) {
    this.isInfinitiveScrollLoaderEnabled = false;
  }

  ngOnInit() {
    window.onscroll = (event) => {
      if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
        console.log('Bottom of page');
        this.ngZone.run(() => {
          this.isInfinitiveScrollLoaderEnabled = true;
        });
      }
    };
  }
}

See this plunkr: https://plnkr.co/edit/PI5wbMnWEY56EiB4wGEH?p=preview . 请参阅以下代码: https ://plnkr.co/edit/PI5wbMnWEY56EiB4wGEH ? p = preview。

It's because the window object is instantiated outside Angular2... 这是因为window对象是在Angular2外部实例化的...

Angular provides an easy way to listen to events on window or document : Angular提供了一种监听windowdocument事件的简便方法:

@Component({
  selector: 'some-class',
  // alternative to @HostListener below
  // host: {'(window:scroll)':'onScroll($event')},
  ...
})
export class SomeClass {
  private isInfinitiveScrollLoaderEnabled: boolean;

  constructor() {
    this.isInfinitiveScrollLoaderEnabled = false;
  }

  @HostListener('window:scroll', ['$event'])
  onScroll(event) {
    if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
      console.log('Bottom of page');
      this.isInfinitiveScrollLoaderEnabled = true;
    }
  }
}

For an imperative way see Programmatically (un)register to event with Angular 2 有关命令式的方法,请参见以编程方式(取消注册)Angular 2中的事件

Günter Zöchbauer's answer is perfect (upvoted). GünterZöchbauer的答案是完美的(赞成)。 I want to explain a bit about it: 我想解释一下:

The Zone library that Angular2 uses internally monkey patches a lot of APIs, including the event listener APIs. Angular2在内部使用Monkey区域的Zone库修补了许多API,包括事件侦听器API。 But this does not include the window/element on<EVENT> properties, maybe because they are considered old and discouraged. 但这不包括on<EVENT>属性on<EVENT>的窗口/元素,可能是因为它们被认为是旧的并且不鼓励使用。

But if you use the addEventListener API, this should work just fine. 但是,如果您使用addEventListener API,则应该可以正常工作。

Example: 例:

export class SomeClass {
  private isInfinitiveScrollLoaderEnabled: boolean;

  constructor(private ngZone: NgZone) {
    this.isInfinitiveScrollLoaderEnabled = false;
  }

  ngOnInit() {
    window.addEventListener('scroll', (event) => {
      if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
        console.log('Bottom of page');
        this.isInfinitiveScrollLoaderEnabled = true;
      }
    });
  }
}

Of course if you can about abstracting away the DOM for use with server rendering or mobile frameworks like NativeScript / ReactNative, you can go for the other valid options 当然,如果您可以抽象出DOM以用于服务器渲染或移动框架(如NativeScript / ReactNative),则可以使用其他有效选项

import {DOM} from 'angular2/platform/common_dom.dart';

DOM
    .getGlobalEventTarget('window')
    .addEventListener('message', function, false);

Or 要么

@HostListener('window:scroll', ['$event'])`

which looks the most declarative to me. 对我来说,这最具说服力。

Both as Günter Zöchbauer mentioned. 正如GünterZöchbauer所述。

If you don't care about these rendering considerations, they might look foreign or so in your code. 如果您不关心这些渲染注意事项,它们在您的代码中可能看起来很陌生。 It's your call either way and should be fine. 无论哪种方式都可以打电话,应该没问题。

Whatever you choose, I'd stay away from the this.ngZone.run() option, because it brings bad memories from the days of $scope.$apply() , although admittedly it's not as bad. 无论您选择什么,我都不会使用this.ngZone.run()选项,因为它在$scope.$apply()年代带来了糟糕的回忆,尽管公认它并不那么糟糕。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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