首页 文章

角度窗口调整大小事件

提问于
浏览
133

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

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

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

谢谢 .

12 回答

  • 22
    <div (window:resize)="onResize($event)"
    
    onResize(event) {
      event.target.innerWidth;
    }
    

    要么

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

    支持的全局目标是 windowdocumentbody .

    在Angular中实现https://github.com/angular/angular/issues/13248之前,性能最好是必须订阅DOM事件,并使用RXJS来减少事件的数量,如其他一些答案中所示 .

  • 46

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

    您还可以在 @Component() -decorator中添加主机绑定 . 您可以将事件和所需的函数调用放在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
       }
    }
    
  • 3

    正确的方法是使用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();
        }
      }
    }
    
  • 334

    这是一个更好的方法 . 基于Birowsky's回答 .

    步骤1:使用RxJS Observables创建 angular service .

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

    对反应式编程的充分理解将始终有助于克服困难问题 . 希望这有助于某人 .

  • 1

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

    import { fromEvent } from "rxjs/observable/fromEvent";
    import { Observable } from "rxjs/Observable";
    import { Subscription } from "rxjs/Subscription";
    

    然后在你的组件中:

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

    假设<600px意味着移动给你,你可以使用这个observable并订阅它:

    首先,我们需要当前的窗口大小 . 因此,我们创建一个只发出单个值的observable:当前窗口大小 .

    initial$ = Observable.of(window.innerWidth > 599 ? false : true);
    

    然后我们需要创建另一个observable,以便我们知道窗口大小何时被更改 . 为此,我们可以使用"fromEvent"运算符 . 要了解有关rxjs`s运营商的更多信息,请访问: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); });
    

    记得取消订阅:)

  • 1

    我还没有见过有人在谈论 angular/cdkMediaMatcher .

    您可以定义MediaQuery并将侦听器附加到它 - 然后在模板(或ts)上的任何位置,如果匹配匹配,您可以调用内容 . 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

  • 0

    基于@cgatian的解决方案,我建议以下简化:

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

    用法:

    import { Component } from '@angular/core';
    import { ResizeService } from './resize-service';
    
    @Component({
      selector: 'my-component',
      template: `{{ rs.onResize$ | async | json }}`
    })
    export class MyComponent {
      constructor(private rs: ResizeService) { }
    }
    
  • 6

    在Angular2(2.1.0)上,我使用ngZone来捕获屏幕更改事件 .

    看看这个例子:

    import { Component, NgZone } from '@angular/core';//import ngZone library
    ...
    //capture screen changed inside constructor
    constructor(private ngZone: NgZone) {
        window.onresize = (e) =>
        {
            ngZone.run(() => {
                console.log(window.innerWidth);
                console.log(window.innerHeight);
            });
        };
    }
    

    我希望这有帮助!

  • 7

    我写了this lib来在Angular中找到一次组件边界大小更改(resize),这可能对其他人有帮助 . 您可以将它放在根组件上,将执行与窗口大小调整相同的操作 .

    Step 1: 导入模块

    import { BoundSensorModule } from 'angular-bound-sensor';
    
    @NgModule({
      (...)
      imports: [
        BoundSensorModule,
      ],
    })
    export class AppModule { }
    

    Step 2: 如下所示添加指令

    <simple-component boundSensor></simple-component>

    Step 3: 接收边界大小详细信息

    import { HostListener } from '@angular/core';
    
    @Component({
      selector: 'simple-component'
      (...)
    })
    class SimpleComponent {
      @HostListener('resize', ['$event'])
      onResize(event) {
        console.log(event.detail);
      }
    }
    
  • 6

    这不是问题的答案,但它可以帮助需要检测任何元素的大小变化的人 .

    我创建了一个库,将 resized 事件添加到任何元素 - Angular Resize Event .

    它内部使用 ResizeSensor 来自CSS Element Queries .

    示例用法

    HTML

    <div (resized)="onResized($event)"></div>
    

    TypeScript

    @Component({...})
    class MyComponent {
      width: number;
      height: number;
    
      onResized(event: ResizedEvent): void {
        this.width = event.newWidth;
        this.height = event.newHeight;
      }
    }
    
  • 26

    下面的代码让我们观察Angular中任何给定div的任何大小更改 .

    <div #observed-div>
    </div>
    

    然后在组件中:

    oldWidth = 0;
    oldHeight = 0;
    
    @ViewChild('observed-div') myDiv: ElementRef;
    ngAfterViewChecked() {
      const newWidth = this.myDiv.nativeElement.offsetWidth;
      const newHeight = this.myDiv.nativeElement.offsetHeight;
      if (this.oldWidth !== newWidth || this.oldHeight !== newHeight)
        console.log('resized!');
    
      this.oldWidth = newWidth;
      this.oldHeight = newHeight;
    }
    

相关问题