我想执行一些基于窗口重新大小事件(在加载和动态)的任务。
目前我的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()
}
我采取的另一种方法是
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可以在任何组件中重用
下面是最新版本的Rxjs对@GiridharKamik答案的更新。
import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject, fromEvent } from 'rxjs';
import { pluck, distinctUntilChanged, map } from 'rxjs/operators';
@Injectable()
export class WindowService {
height$: Observable<number>;
constructor() {
const windowSize$ = new BehaviorSubject(getWindowSize());
this.height$ = windowSize$.pipe(pluck('height'), distinctUntilChanged());
fromEvent(window, 'resize').pipe(map(getWindowSize))
.subscribe(windowSize$);
}
}
function getWindowSize() {
return {
height: window.innerHeight
//you can sense other parameters here
};
};
如果你想在调整大小完成后只发生一个事件,最好使用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');
});
堆栈闪电战
正确的方法是利用EventManager类来绑定事件。这让你的代码可以在其他平台上工作,例如使用Angular Universal进行服务器端渲染。
import { EventManager } from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Injectable } from '@angular/core';
@Injectable()
export class ResizeService {
get onResize$(): Observable<Window> {
return this.resizeSubject.asObservable();
}
private resizeSubject: Subject<Window>;
constructor(private eventManager: EventManager) {
this.resizeSubject = new Subject();
this.eventManager.addGlobalEventListener('window', 'resize', this.onResize.bind(this));
}
private onResize(event: UIEvent) {
this.resizeSubject.next(<Window>event.target);
}
}
在组件中使用这个服务非常简单,只需将这个服务作为提供者添加到app.module中,然后在组件的构造函数中导入它。
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-component',
template: ``,
styles: [``]
})
export class MyComponent implements OnInit {
private resizeSubscription: Subscription;
constructor(private resizeService: ResizeService) { }
ngOnInit() {
this.resizeSubscription = this.resizeService.onResize$
.subscribe(size => console.log(size));
}
ngOnDestroy() {
if (this.resizeSubscription) {
this.resizeSubscription.unsubscribe();
}
}
}
假设< 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); });
记得取消订阅:)