[英]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提供了一种监听
window
或document
事件的简便方法:
@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.