角度性能:如果组件不在视口中,则更改检测分离 [英] Angular performance: change detection detached if component is out of viewport

查看:74
本文介绍了角度性能:如果组件不在视口中,则更改检测分离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要从当前视口中分离所有组件的更改检测

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);
}

这篇关于角度性能:如果组件不在视口中,则更改检测分离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆