我想执行一些基于窗口重新大小事件(在加载和动态)的任务。
目前我的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可以在任何组件中重用
假设< 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来减少事件的数量(如其他一些答案所示)会更好地提高性能。