角度窗口调整大小性能

问题描述 投票:0回答:1

我正在创建一个 Angular 响应式应用程序,其中有超过 10 个断点,我必须将元素分组到不同的容器中。考虑到这一点,我相信我无法利用 css mediaQueris,并且我希望在组件中拥有窗口的 innerWidth 属性。

为了获得它,我创建了以下指令,并用它扩展了组件:

import { Directive, NgZone, OnDestroy } from "@angular/core";
import { Subject, fromEvent } from "rxjs";
import { debounceTime, distinctUntilChanged, map, takeUntil } from "rxjs/operators";

@Directive()
export abstract class WindowResizeDirective implements OnDestroy {
    winWidth: number = window.innerWidth;

    protected destroy$: Subject<boolean> = new Subject();

    constructor(private _zone: NgZone) {
        this._zone.runOutsideAngular(() => {
            fromEvent(window, 'resize').pipe(
                debounceTime(300),
                map((ev: any) => ev.target.innerWidth),
                distinctUntilChanged(),
                takeUntil(this.destroy$)
            ).subscribe(width => {
                this._zone.run(() => {
                    this.winWidth = width;
                })
            });
        });
    }

    ngOnDestroy(): void {
        this.destroy$.next(true);
        this.destroy$.complete();
      }
}

然而,很多时候我需要使用页面组件的这个指令一次,而不是在页面组件的许多子组件上使用,因此,由于同一个原因 -> 调整窗口大小,会触发很多更改检测周期。您能建议一种提高性能的方法吗?

  1. 我一直在考虑使用服务而不是在父级别提供的指令,并且每个孩子都可以获得相同的服务实例。
  2. 我不确定指令中的代码是否是最佳的。

如有任何建议,我们将不胜感激。

angular angular-directive angular-services window-resize
1个回答
0
投票

我想这里有一个服务会更好,创建一个调整大小服务来处理跨多个组件的窗口调整大小事件。

使用BehaviorSubject来保存当前窗口宽度

类似这样的:

import { Injectable, NgZone, OnDestroy } from '@angular/core';
import { BehaviorSubject, fromEvent } from 'rxjs';
import { debounceTime, map, takeUntil } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class ResizeService implements OnDestroy {
  private windowSize = new BehaviorSubject<number>(window.innerWidth);
  private destroy$ = new Subject<void>();

  constructor(private zone: NgZone) {
    this.zone.runOutsideAngular(() => {
      fromEvent(window, 'resize').pipe(
        debounceTime(300),
        map((event: any) => event.target.innerWidth),
        takeUntil(this.destroy$),
      ).subscribe(width => {
        this.zone.run(() => {
          this.windowSize.next(width);
        });
      });
    });
  }

  getWindowSize(): BehaviorSubject<number> {
    return this.windowSize;
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

将其注入到您的组件中

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { ResizeService } from './resize.service';

@Component({
  selector: 'app-some-component',
  template: `<!-- Your template here -->`,
})
export class SomeComponent implements OnInit, OnDestroy {
  private resizeSubscription: Subscription;
  winWidth: number;

  constructor(private resizeService: ResizeService) {}

  ngOnInit() {
    this.resizeSubscription = this.resizeService.getWindowSize().subscribe(width => {
      this.winWidth = width;
    });
  }

  ngOnDestroy() {
    if (this.resizeSubscription) {
      this.resizeSubscription.unsubscribe();
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.