我想执行一些基于窗口重新大小事件(在加载和动态)的任务。

目前我的DOM如下:

<div id="Harbour">
    <div id="Port" (window:resize)="onResize($event)" >
        <router-outlet></router-outlet>
    </div>
</div>

事件正确触发

export class AppComponent {
    onResize(event) {
        console.log(event);
    }
}

我如何从这个事件对象检索宽度和高度?

谢谢。


当前回答

我采取的另一种方法是

import {Component, OnInit} from '@angular/core';
import {fromEvent} from "rxjs";
import {debounceTime, map, startWith} from "rxjs/operators";


function windowSizeObserver(dTime = 300) {
  return fromEvent(window, 'resize').pipe(
    debounceTime(dTime),
    map(event => {
      const window = event.target as Window;

      return {width: window.innerWidth, height: window.innerHeight}
    }),
    startWith({width: window.innerWidth, height: window.innerHeight})
  );
}

@Component({
  selector: 'app-root',
  template: `
    <h2>Window Size</h2>
    <div>
      <span>Height: {{(windowSize$ | async)?.height}}</span>
      <span>Width: {{(windowSize$ | async)?.width}}</span>
    </div>
  `
})
export class WindowSizeTestComponent {
  windowSize$ = windowSizeObserver();
}

这里的windowSizeObserver可以在任何组件中重用

其他回答

下面的代码让我们观察Angular中任何给定div的大小变化。

<div #observed-div>
</div>

然后在组件中:

oldWidth = 0;
oldHeight = 0;

@ViewChild('observed-div') myDiv: ElementRef;
ngAfterViewChecked() {
  const newWidth = this.myDiv.nativeElement.offsetWidth;
  const newHeight = this.myDiv.nativeElement.offsetHeight;
  if (this.oldWidth !== newWidth || this.oldHeight !== newHeight)
    console.log('resized!');

  this.oldWidth = newWidth;
  this.oldHeight = newHeight;
}

假设< 600px对你来说意味着移动,你可以使用这个可观察对象并订阅它:

首先,我们需要当前窗口大小。因此,我们创建了一个只发出一个值的可观察对象:当前窗口大小。

initial$ = Observable.of(window.innerWidth > 599 ? false : true);

然后我们需要创建另一个可观察对象,这样我们就知道窗口大小什么时候被改变了。为此,我们可以使用“fromEvent”操作符。要了解更多关于rxjs的操作符,请访问:rxjs

resize$ = Observable.fromEvent(window, 'resize').map((event: any) => {
  return event.target.innerWidth > 599 ? false : true;
 });

合并这两个流来接收我们的可观察对象:

mobile$ = Observable.merge(this.resize$, this.initial$).distinctUntilChanged();

现在你可以像这样订阅它:

mobile$.subscribe((event) => { console.log(event); });

记得取消订阅:)

这是我创建的一个简单而干净的解决方案,这样我就可以将它注入到多个组件中。

ResizeService.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ResizeService {

  constructor() {

    window.addEventListener('resize', (e) => {
      this.onResize.next();
    });

  }

  public onResize = new Subject();

}

在使用:

constructor(
  private resizeService: ResizeService
) { 

  this.subscriptions.push(this.resizeService.onResize.subscribe(() => {
    // Do stuff
  }));

}

private subscriptions: Subscription[] = [];

@Günter的答案是正确的。我只是想提出另一种方法。

你也可以在@Component()装饰器中添加主机绑定。你可以像这样把事件和所需的函数调用放在host-metadata-property中:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  host: {
    '(window:resize)': 'onResize($event)'
  }
})
export class AppComponent{
   onResize(event){
     event.target.innerWidth; // window width
   }
}
<div (window:resize)="onResize($event)"
onResize(event) {
  event.target.innerWidth;
}

或者使用HostListener装饰器:

@HostListener('window:resize', ['$event'])
onResize(event) {
  event.target.innerWidth;
}

支持的全局目标有window、document和body。

在https://github.com/angular/angular/issues/13248在Angular中实现之前,强制订阅DOM事件并使用RXJS来减少事件的数量(如其他一些答案所示)会更好地提高性能。