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

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

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

谢谢。


当前回答

我还没看到有人在谈论angular/cdk的MediaMatcher。

您可以定义一个MediaQuery并将一个侦听器附加到它-然后在模板(或ts)上的任何地方,如果匹配了Matcher,就可以调用东西。 LiveExample

App.Component.ts

import {Component, ChangeDetectorRef} from '@angular/core';
import {MediaMatcher} from '@angular/cdk/layout';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  mobileQuery: MediaQueryList;

  constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher) {
    this.mobileQuery = media.matchMedia('(max-width: 600px)');
    this._mobileQueryListener = () => changeDetectorRef.detectChanges();
    this.mobileQuery.addListener(this._mobileQueryListener);
  }

  private _mobileQueryListener: () => void;

  ngOnDestroy() {
    this.mobileQuery.removeListener(this._mobileQueryListener);
  }

}

App.Component.Html

<div [class]="mobileQuery.matches ? 'text-red' : 'text-blue'"> I turn red on mobile mode 
</div>

App.Component.css

.text-red { 
   color: red;
}

.text-blue {
   color: blue;
}

来源:https://material.angular.io/components/sidenav/overview

其他回答

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

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

我所做的就像Johannes Hoppe建议的那样:

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', event => this.onResize$.emit({ width: event.target.innerWidth, height: event.target.innerHeight })); } getWindowSize(){ this.onResize$.emit({ width: window.innerWidth, height: window.innerHeight }); } }

在app.component.ts:

Import { ResizeService } from ".shared/services/resize.service" import { Component } from "@angular/core" @Component({ selector: "app-root", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"] }) export class AppComponent{ windowSize: {width: number, height: number}; constructor(private resizeService: ResizeService){ } ngOnInit(){ this.resizeService.onResize$.subscribe((value) => { this.windowSize = value; }); this.resizeService.getWindowSize(); } }

然后在你的app.component.html中:

<router-outlet *ngIf = "windowSize? "宽度> 1280 && windowSize?。高度> 700;errorComponent”> < / router-outlet > < ng-template # errorComponent > < app-error-component > < / app-error-component > < / ng-template >

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

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

这里有一个更好的方法。根据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
        });
    }

}

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