我想从当前视口(viewport)中分离所有组件的更改检测
import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef, ElementRef, ViewChild, OnInit, OnDestroy, AfterViewInit } from '@angular/core';
@Component({
selector: 'hello',
template: `<div #counter>[{{index}}] {{count}}</div>`,
styles: [`div { border: 1px solid red; padding: 5px 5px 5px 5px; }`],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HelloComponent implements OnInit, AfterViewInit {
@ViewChild('counter', { static: false }) counter: ElementRef;
@Input() index: number;
public count = 0;
public visible = true;
constructor(private cdr: ChangeDetectorRef){}
ngOnInit() {
setInterval(() => {
this.count++;
this.cdr.markForCheck();
}, 1000);
}
ngAfterViewInit() {
const hideWhenBoxInView = new IntersectionObserver((entries) => {
if (entries[0].intersectionRatio <= 0) { // If not in view
this.cdr.detach();
this.visible = false;
} else {
this.visible = true;
this.cdr.reattach();
this.cdr.markForCheck();
}
// console.log(this.index, this.visible);
});
hideWhenBoxInView.observe(this.counter.nativeElement);
}
}
它可以工作,但是有超过 1000 个组件时,性能非常糟糕。
我的附加/分离更改检测正确吗?
最佳答案
您正在为每个组件调用 setInterval()
,包括那些不在 View 中的组件。更改检测未运行,但您仍然每秒调用 setInterval() 中的函数 1000 次,这解释了延迟。
顺便说一句,渲染包含 1000 个项目的滚动列表也会影响性能。尽管在视口(viewport)之外,但浏览器将渲染所有内容,并且在滚动列表时需要计算各种绘制。您应该延迟渲染这么长的列表,请参阅 Virtual Scrolling in Angular 7
您还在 View 之外的组件上调用 .markForCheck()
,请在调用之前检查组件是否可见。
ngOnInit() {
this.subscriptions.add(
interval(1000).subscribe(() => {
this.count++;
if (this.visible) {
this.cdr.markForCheck();
}
})
);
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
ngAfterViewInit() {
const hideWhenBoxInView = new IntersectionObserver(entries => {
if (entries[0].intersectionRatio <= 0) {
// If not in view
this.cdr.detach();
this.visible = false;
} else {
this.visible = true;
this.cdr.reattach();
this.cdr.markForCheck();
}
});
hideWhenBoxInView.observe(this.counter.nativeElement);
}
关于javascript - Angular 性能: change detection detached if component is out of viewport,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59248167/