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

目前我的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);
    }
}

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

谢谢。


当前回答

如果你想在调整大小完成后只发生一个事件,最好使用RxJS和debounceTime: debounceTime:丢弃输出间隔时间少于指定时间的发出值。

在运行代码之前,他在两个事件之间等待> 0.5s。 简单地说,它在执行下一个代码之前等待大小调整完成。

// RxJS v6+
import { fromEvent } from 'rxjs';
import { debounceTime, map } from 'rxjs/operators';

...

const resize$ = fromEvent(window, 'resize');
    resize$
      .pipe(
        map((i: any) => i),
        debounceTime(500) // He waits > 0.5s between 2 events emitted before running the next.
      )
      .subscribe((event) => {
        console.log('resize is finished');
      });

堆栈闪电战

其他回答

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

记得取消订阅:)

下面的代码让我们观察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;
}

基于@cgatian的解决方案,我建议简化如下:

import { EventManager } from '@angular/platform-browser';
import { Injectable, EventEmitter } from '@angular/core';

@Injectable()
export class ResizeService {

  public onResize$ = new EventEmitter<{ width: number; height: number; }>();

  constructor(eventManager: EventManager) {
    eventManager.addGlobalEventListener('window', 'resize',
      e => this.onResize$.emit({
        width: e.target.innerWidth,
        height: e.target.innerHeight
      }));
  }
}

用法:

import { Component } from '@angular/core';
import { ResizeService } from './resize-service';

@Component({
  selector: 'my-component',
  template: `{{ rs.onResize$ | async | json }}`
})
export class MyComponent {
  constructor(private rs: ResizeService) { }
}

这里有一个更好的方法。根据Birowsky的回答。

步骤1:用RxJS observable创建一个angular服务。

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';

@Injectable()
export class WindowService {
    height$: Observable<number>;
    //create more Observables as and when needed for various properties
    hello: string = "Hello";
    constructor() {
        let windowSize$ = new BehaviorSubject(getWindowSize());

        this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();

        Observable.fromEvent(window, 'resize')
            .map(getWindowSize)
            .subscribe(windowSize$);
    }

}

function getWindowSize() {
    return {
        height: window.innerHeight
        //you can sense other parameters here
    };
};

步骤2:注入上述服务,并订阅在服务中创建的任何可观察对象,无论您希望在哪里接收窗口大小调整事件。

import { Component } from '@angular/core';
//import service
import { WindowService } from '../Services/window.service';

@Component({
    selector: 'pm-app',
    templateUrl: './componentTemplates/app.component.html',
    providers: [WindowService]
})
export class AppComponent { 

    constructor(private windowService: WindowService) {

        //subscribe to the window resize event
        windowService.height$.subscribe((value:any) => {
            //Do whatever you want with the value.
            //You can also subscribe to other observables of the service
        });
    }

}

充分理解响应式编程总是有助于克服困难的问题。希望这能帮助到一些人。

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

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