角度窗口调整大小事件

IT技术 javascript angular
2021-01-15 15:51:32

我想根据窗口大小调整事件(加载和动态)执行一些任务。

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

如何从此事件对象中检索宽度和高度?

谢谢。

6个回答
<div (window:resize)="onResize($event)"
onResize(event) {
  event.target.innerWidth;
}

或使用HostListener 装饰器

@HostListener('window:resize', ['$event'])
onResize(event) {
  event.target.innerWidth;
}

支持的全球目标是windowdocumentbody

在 Angular 中实现https://github.com/angular/angular/issues/13248之前,强制订阅 DOM 事件并使用 RXJS 来减少事件数量会更好地提高性能,如其他一些答案所示。

确切地。您可以使用documentwindowbody github.com/angular/angular/blob/...
2021-03-31 15:51:32
当然,但是,对于那些想知道 HostListener 与debounceTime如何工作的人,请点击以下链接plnkr.co/edit/3J0dcDaLTJBxkzo8Akyg?p=preview
2021-04-07 15:51:32
是否有关于您使用的语法的任何文档: window:resize
2021-04-09 15:51:32
快速提示:如果也想在第一次加载时触发,请从@angular/core 实现 ngAfterViewInit。angular.io/api/core/AfterViewInit
2021-04-09 15:51:32
完美的答案..我确实相信@HostListener 是更干净的方式:) 但请确保首先使用导入 HostListener import { Component, OnInit, HostListener } from '@angular/core';
2021-04-11 15:51:32

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

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

然后一定要在销毁时取消订阅!

ngOnDestroy() {
    this.resizeSubscription$.unsubscribe()
}
尽管debounceTime较少使用和运行您的订阅回调,Angular 将在每个事件上运行更改检测,因为它是在区域内触发的。您应该检查我的答案以消除此问题。
2021-03-12 15:51:32
我可以在哪里添加 debounce(1000) ?
2021-03-17 15:51:32
唯一对我有用的方法。谢谢!!:-) ...我只需要调整您的导入。也许我的 rxjs 更新了:import { fromEvent, Observable,Subscription } from "rxjs";
2021-03-23 15:51:32
对于去抖动,从 'rxjs/operators' 导入 { debounceTime };
2021-03-24 15:51:32
抱歉回复晚了:要添加去抖动,您需要使用 this.resizeSubscription$ = this.resizeObservable$.pipe(debounceTime(1000)).subscribe( evt => { console.log('event: ', evt) })
2021-03-31 15:51:32

@Günter 的回答是正确的。我只是想提出另一种方法。

您还可以在@Component()-decorator 中添加主机绑定您可以将事件和所需的函数调用放在主机元数据属性中,如下所示:

@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
   }
}
加载时如何获得视口高度?
2021-03-19 15:51:32
我已经尝试了此页面上的所有方法,但似乎都不起作用。有没有关于这个的官方文档。
2021-03-21 15:51:32
@GiridharKarnik,你有没有试过做一个window.innerWidth内部ngOnInitngAfterViewInit方法?
2021-03-31 15:51:32
是如何使用它的参考
2021-04-03 15:51:32
@Tomato API 参考可以在这里找到许多参考是自动生成的(我认为),并且缺乏示例或详细说明。一些 api-references 有很多例子。尽管如此,我无法从文档中找到一个具体的例子。也许它隐藏在某处:P
2021-04-09 15:51:32

正确的做法是利用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();
    }
  }
}
@cgatian 我是个菜鸟,但这似乎是正确的答案。不幸的是,我没有运气使我的订阅登录组件。您能否在答案中添加如何在组件中订阅它以便人们可以看到更新?
2021-03-13 15:51:32
据我所知,这不会在移动设备上触发。您如何使用这种方法获得初始窗口大小?
2021-03-17 15:51:32
Mobile 没有window对象,就像服务器没有window. 我不熟悉不同的移动配置,但您应该能够轻松调整上述代码以绑定到正确的全局事件侦听器
2021-03-18 15:51:32
@cgatian 我会做一个 plunker 但这似乎不起作用。服务中的过滤器看起来很奇怪stackoverflow.com/q/46397531/1191635
2021-03-25 15:51:32
@cgatian Mobile does not have a window object.... 为什么你认为移动浏览器没有 window 对象?
2021-03-27 15:51:32

这是一个更好的方法。基于比罗斯基的回答。

第 1 步:angular service使用 RxJS Observables创建一个

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 步:注入上述内容service并订阅Observables服务中创建的任何您希望接收窗口大小调整事件的地方。

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

}

对react式编程的充分理解总是有助于克服困难的问题。希望这可以帮助某人。

当您在 Angular 之外执行此事件时,不会触发更改检测,相信这就是他的意思。
2021-03-17 15:51:32
没听懂,请多多指教。
2021-03-18 15:51:32
我有一个错误,说 BehaviorSubject 类型上不存在“pluck”。将代码更改为 this.height$ = windowSize$.map(x => x.height) 对我有用。
2021-03-27 15:51:32
@GiridharKamik 你能提供一个可以同时订阅宽度和高度的解决方案吗,我们可以在 1 个简单订阅中同时订阅宽度和高度
2021-04-02 15:51:32
我相信这是一个错误: this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();Observable<number>).distinctUntilChanged(); 看起来你连续两次粘贴了 distinctUntilChanged()
2021-04-11 15:51:32