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

目前我的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 { fromEvent, Observable, Subscription } from "rxjs";

然后在你的组件中:

resizeObservable$: Observable<Event>
resizeSubscription$: Subscription

ngOnInit() {
    this.resizeObservable$ = fromEvent(window, 'resize')
    this.resizeSubscription$ = this.resizeObservable$.subscribe( evt => {
      console.log('event: ', evt)
    })
}

那么一定要取消订阅destroy!

ngOnDestroy() {
    this.resizeSubscription$.unsubscribe()
}

其他回答

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

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[] = [];

我知道很久以前就有人问过这个问题,但现在有更好的方法来做到这一点!我不确定是否有人会看到这个答案。显然你的进口:

import { fromEvent, Observable, Subscription } from "rxjs";

然后在你的组件中:

resizeObservable$: Observable<Event>
resizeSubscription$: Subscription

ngOnInit() {
    this.resizeObservable$ = fromEvent(window, 'resize')
    this.resizeSubscription$ = this.resizeObservable$.subscribe( evt => {
      console.log('event: ', evt)
    })
}

那么一定要取消订阅destroy!

ngOnDestroy() {
    this.resizeSubscription$.unsubscribe()
}

@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
   }
}

我采取的另一种方法是

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可以在任何组件中重用

<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来减少事件的数量(如其他一些答案所示)会更好地提高性能。