我要从当前视口中分离所有组件的更改检测
I want detach the change detection for all the compontents out of the current 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多个组件,性能非常差.
it works, but with over 1000 components the performance is very bad.
我的附加/分离更改检测是否正确?
Are my attaching/detaching change detection correct?
推荐答案您正在为每个组件(包括那些不在视图中的组件)调用setInterval().更改检测未运行,但您仍以每秒setInterval()的速度调用该函数1000次,这说明了延迟.
You are calling setInterval() for every component including those that are not in view. Change detection is not running but you are still calling the function in setInterval() 1000 times per second which explains the lag.
顺便说一句,渲染包含1000个项目的滚动列表也会影响性能.浏览器将渲染所有内容,并且尽管不在视口范围内,但在滚动列表时仍需要计算各种绘制.您应该懒惰地渲染这么长的列表,请参见在Angular 7中进行虚拟滚动
By the way, rendering a scroll list with 1000 items affects performance too. Browsers will render everything and need to calculate various paints when scrolling through the list despite being out of viewport. You should render such long list lazily, see Virtual Scrolling in Angular 7
您还要在看不见的组件上调用.markForCheck(),请在调用该组件之前检查该组件是否可见.
You are also calling .markForCheck() on components that are out of view, check whether component is visible before calling that.
请参见 StackBlitz
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); }
更多推荐
角度性能:如果组件不在视口中,则更改检测分离
发布评论