使用Angular 4检测窗口大小

Ron*_*men 75 angular

我一直在尝试构建一个响应式导航栏,并且不希望使用媒体查询,所以我打算使用*ngIF窗口大小作为标准.但我一直面临一个问题,因为我无法找到任何关于Angular 4窗口大小检测的方法或文档.我也尝试过JavaScript方法,但不支持.

我也尝试过以下方法:

constructor(platform: Platform) {
    platform.ready().then((readySource) => {
        console.log('Width: ' + platform.width());
        console.log('Height: ' + platform.height());
    });
}
Run Code Online (Sandbox Code Playgroud)

...用于离子.

并且screen.availHeight,但仍然没有成功.

Edu*_*gas 183

在init上获取它

public innerWidth: any;
ngOnInit() {
    this.innerWidth = window.innerWidth;
}
Run Code Online (Sandbox Code Playgroud)

如果你想在调整大小时保持更新:

@HostListener('window:resize', ['$event'])
onResize(event) {
  this.innerWidth = window.innerWidth;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您正在使用 lodash,也建议在构造函数中使用它 ... this.onResize = debounce(this.onResize, 150, {leading: false, trailing: true}) ... 以防止 onResize 方法被过于频繁地调用.. . 你需要... import { debounce } from 'lodash' (3认同)
  • this.innerWidth = event.target.innerWidth; ...可能更有效,产生相同的结果 (2认同)

Jer*_*nks 20

如果您想对某些断点做出反应(例如,如果宽度小于768px则执行某些操作),您还可以使用BreakpointObserver:

import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout';

{ ... }

const isSmallScreen = breakpointObserver.isMatched('(max-width: 599px)');
Run Code Online (Sandbox Code Playgroud)

甚至听取对该断点的更改:

breakpointObserver.observe([
  '(max-width: 768px)'
    ]).subscribe(result => {
      if (result.matches) {
        doSomething();
      } else {
        // if necessary:
        doSomethingElse();
      }
    });
Run Code Online (Sandbox Code Playgroud)


小智 12

这是我使用的服务示例。

您可以通过订阅screenWidth$或通过来获取屏幕宽度screenWidth$.value

对于mediaBreakpoint$( 或mediaBreakpoint$.value) 也是如此

import {
  Injectable,
  OnDestroy,
} from '@angular/core';
import {
  Subject,
  BehaviorSubject,
  fromEvent,
} from 'rxjs';
import {
  takeUntil,
  debounceTime,
} from 'rxjs/operators';

@Injectable()
export class ResponsiveService implements OnDestroy {
  private _unsubscriber$: Subject<any> = new Subject();
  public screenWidth$: BehaviorSubject<number> = new BehaviorSubject(null);
  public mediaBreakpoint$: BehaviorSubject<string> = new BehaviorSubject(null);

  constructor() {
    this.init();
  }

  init() {
    this._setScreenWidth(window.innerWidth);
    this._setMediaBreakpoint(window.innerWidth);
    fromEvent(window, 'resize')
      .pipe(
        debounceTime(1000),
        takeUntil(this._unsubscriber$)
      ).subscribe((evt: any) => {
        this._setScreenWidth(evt.target.innerWidth);
        this._setMediaBreakpoint(evt.target.innerWidth);
      });
  }

  ngOnDestroy() {
    this._unsubscriber$.next();
    this._unsubscriber$.complete();
  }

  private _setScreenWidth(width: number): void {
    this.screenWidth$.next(width);
  }

  private _setMediaBreakpoint(width: number): void {
    if (width < 576) {
      this.mediaBreakpoint$.next('xs');
    } else if (width >= 576 && width < 768) {
      this.mediaBreakpoint$.next('sm');
    } else if (width >= 768 && width < 992) {
      this.mediaBreakpoint$.next('md');
    } else if (width >= 992 && width < 1200) {
      this.mediaBreakpoint$.next('lg');
    } else if (width >= 1200 && width < 1600) {
      this.mediaBreakpoint$.next('xl');
    } else {
      this.mediaBreakpoint$.next('xxl');
    }
  }

}

Run Code Online (Sandbox Code Playgroud)

希望这有助于某人


Roh*_*yen 9

对于这种情况,您可以使用 typescript getter 方法。像这样

public get width() {
  return window.innerWidth;
}
Run Code Online (Sandbox Code Playgroud)

并在模板中使用它,如下所示:

<section [ngClass]="{ 'desktop-view': width >= 768, 'mobile-view': width < 768 
}"></section>
Run Code Online (Sandbox Code Playgroud)

您不需要任何事件处理程序来检查窗口的大小调整,此方法将每次自动检查大小。


rob*_*nnn 7

文件Platform width()height(),并说明这些方法分别使用window.innerWidthwindow.innerHeight.但是使用这些方法是优先的,因为维度是缓存值,这减少了多次和昂贵的DOM读取的机会.

import { Platform } from 'ionic-angular';

...
private width:number;
private height:number;

constructor(private platform: Platform){
    platform.ready().then(() => {
        this.width = platform.width();
        this.height = platform.height();
    });
}
Run Code Online (Sandbox Code Playgroud)


Har*_*jan 7

答案很简单。编写下面的代码

import { Component, OnInit, OnDestroy, Input } from "@angular/core";
// Import this, and write at the top of your .ts file
import { HostListener } from "@angular/core";

@Component({
 selector: "app-login",
 templateUrl: './login.component.html',
 styleUrls: ['./login.component.css']
})

export class LoginComponent implements OnInit, OnDestroy {
// Declare height and width variables
scrHeight:any;
scrWidth:any;

@HostListener('window:resize', ['$event'])
getScreenSize(event?) {
      this.scrHeight = window.innerHeight;
      this.scrWidth = window.innerWidth;
      console.log(this.scrHeight, this.scrWidth);
}

// Constructor
constructor() {
    this.getScreenSize();
}
}
Run Code Online (Sandbox Code Playgroud)


Moh*_*tly 7

现在我知道问题最初是指屏幕尺寸,所以基本上是widthheight属性,但对于大多数人来说,Breakpoints真正重要的是,因此,为了制定一个全局可重用的解决方案,我更喜欢使用来处理这个Angular问题BreakpointObserver

以下配置基本上是可以service在任何需要的地方进行的:functionsreturnObservable<BreakpointState>subscribed

import { Injectable } from '@angular/core';
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class ScreenService {

  constructor(private observer: BreakpointObserver) {}

  isBelowSm(): Observable<BreakpointState> {
    return this.observer.observe(['(max-width: 575px)']);
  }

  isBelowMd(): Observable<BreakpointState> {
    return this.observer.observe(['(max-width: 767px)']);
  }

  isBelowLg(): Observable<BreakpointState> {
    return this.observer.observe(['(max-width: 991px)']);
  }

  isBelowXl(): Observable<BreakpointState> {
    return this.observer.observe(['(max-width: 1199px)']);
  }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码可以调整以处理屏幕尺寸的bootstrap方式(通过更改max-widthmin-width并添加1px每个值,当然还有反转function名称。

现在在 中component class,只需subscribing返回observable上述任何函数即可。

IE:app.component.ts

export class AppComponent implements AfterViewInit {

  isBelowLg: boolean;

  constructor(private screenService: ScreenService) {}

  ngAfterViewInit(): void {
    this.screenService.isBelowLg().subscribe((isBelowLg: BreakpointState) => {
      this.isBelowLg = isBelowLg.matches;
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在视图初始化后,使用AfterViewInit生命周期钩子会省去很多麻烦。detectChanges()

编辑:

作为替代方案,AfterViewInit它是相同的,但此外,您需要使用ChangeDetectorRefto detectChanges(),只需在订阅组件中注入一个实例即可app.component.ts如下所示:

constructor(
    private screenService: ScreenService,
    private cdref: ChangeDetectorRef
  ) {}
Run Code Online (Sandbox Code Playgroud)

之后,只需调用detectChanges()即可:

this.cdref.detectChanges();
Run Code Online (Sandbox Code Playgroud)


Dhr*_*ekh 6

@HostListener("window:resize", [])
public onResize() {
  this.detectScreenSize();
}

public ngAfterViewInit() {
    this.detectScreenSize();
}

private detectScreenSize() {
    const height = window.innerHeight;
    const width = window.innerWidth;
}
Run Code Online (Sandbox Code Playgroud)

  • 始终解释为什么这可能是正确的解决方案 (7认同)

Fab*_*sco 5

你可以使用这个 https://github.com/ManuCutillas/ng2-responsive 希望它有帮助:-)


Kil*_*are 5

如果希望组件易于测试,则应将全局窗口对象包装在Angular Service中:

import { Injectable } from '@angular/core';

@Injectable()
export class WindowService {

  get windowRef() {
    return window;
  }

}
Run Code Online (Sandbox Code Playgroud)

然后,您可以像其他任何服务一样注入它:

constructor(
    private windowService: WindowService
) { }
Run Code Online (Sandbox Code Playgroud)

消耗...

  ngOnInit() {
      const width= this.windowService.windowRef.innerWidth;
  }
Run Code Online (Sandbox Code Playgroud)

  • 首先,DI 是 Angular 方式,使组件/指令的依赖关系更加清晰。但这里提到的要点是让使用服务的代码更容易测试。使用这种方法,可以在为使用该服务的组件编写的任何测试中模拟 WindowService。 (7认同)
  • 我看不出做一项服务来完全完成手头上的事情的意义。窗口.内宽度。 (5认同)