我想执行一些基于窗口重新大小事件(在加载和动态)的任务。
目前我的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可以在任何组件中重用
我所做的就像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 >
我写这个库是为了找到Angular中组件边界大小改变(重新调整大小)的方法,希望能帮助到其他人。你可以把它放在根组件上,会做和窗口大小调整一样的事情。
步骤1:导入模块
import { BoundSensorModule } from 'angular-bound-sensor';
@NgModule({
(...)
imports: [
BoundSensorModule,
],
})
export class AppModule { }
步骤2:添加如下指令
<简单的组件boundSensor > < /简单的组件>
步骤3:接收边界大小的详细信息
import { HostListener } from '@angular/core';
@Component({
selector: 'simple-component'
(...)
})
class SimpleComponent {
@HostListener('resize', ['$event'])
onResize(event) {
console.log(event.detail);
}
}
<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来减少事件的数量(如其他一些答案所示)会更好地提高性能。
我采取的另一种方法是
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可以在任何组件中重用
在angular CDK中有一个ViewportRuler服务。它在区域外运行,支持方向改变和大小调整。它也适用于服务器端渲染。
@Component({
selector: 'my-app',
template: `
<p>Viewport size: {{ width }} x {{ height }}</p>
`
})
export class AppComponent implements OnDestroy {
width: number;
height: number;
private readonly viewportChange = this.viewportRuler
.change(200)
.subscribe(() => this.ngZone.run(() => this.setSize()));
constructor(
private readonly viewportRuler: ViewportRuler,
private readonly ngZone: NgZone
) {
// Change happens well, on change. The first load is not a change, so we init the values here. (You can use `startWith` operator too.)
this.setSize();
}
// Never forget to unsubscribe!
ngOnDestroy() {
this.viewportChange.unsubscribe();
}
private setSize() {
const { width, height } = this.viewportRuler.getViewportSize();
this.width = width;
this.height = height;
}
}
ViewportRuler的Stackblitz示例
好处是,它限制了更改检测周期(它只会在区域中运行回调时触发),而(window:resize)将在每次调用时触发更改检测。