Angular CDK有一个布局包,其服务可以轻松检测窗口大小并与媒体查询匹配。这使得你可以完全控制UI并适应不同的屏幕尺寸。
让我们快速了解一下如何使用CDK的布局模块。
首先,您需要确保在您的应用中安装了Angular CDK:
$ npm install @angular/cdk # or, using Yarn: $ yarn add @angular/cdk
然后导入布局模块,并将其添加到NgModule的导入列表中:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { LayoutModule } from '@angular/cdk/layout'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, LayoutModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
你现在可以在组件中开始使用service了。
BreakpointObserver本身是一个service,并且它有两个方法,分别是isMatched和observe。
observe方法返回一个可被观察的BreakpointState类型对象,可以用于观察窗口何时在匹配媒体查询之间发生变化。
Demo 1
下面是一个简单的示例,如果窗口大小在小于500px且等于或者大于500px之间变化,则会将消息打印到控制台。
import { Component, OnInit } from '@angular/core'; import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout'; @Component({ ... }) export class AppComponent implements OnInit { constructor(public breakpointObserver: BreakpointObserver) {} ngOnInit() { this.breakpointObserver .observe(['(min-width: 500px)']) .subscribe((state: BreakpointState) => { if (state.matches) { console.log('Viewport is 500px or over!'); } else { console.log('Viewport is getting smaller!'); } }); } }
BreakpointState接口为我们提供了一个名为matches的布尔属性。
Demo 2
我们也可以使用Breakpoints对象,而不是使用手写的媒体查询,它为我们提供了常见断点的键:
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout'; @Component({ ... }) export class AppComponent implements OnInit { constructor(public breakpointObserver: BreakpointObserver) {} ngOnInit() { this.breakpointObserver .observe([Breakpoints.Small, Breakpoints.HandsetPortrait]) .subscribe((state: BreakpointState) => { if (state.matches) { console.log( 'Matches small viewport or handset in portrait mode' ); } }); } }
portrait为竖屏显示,landscape为横屏显示。
对于简单的一次性匹配,可以使用isMatching方法。如果组件初始化时窗口至少为40rem高,则输出到控制台。
// ... ngOnInit() { if (this.breakpointObserver.isMatched('(min-height: 40rem)')) { console.log('Enough room!'); } } // ...
MediaMatcher是一个包含javascript的matchMedia的service。与BreakpointObserver.observe一样,他可以用于观察窗口大小相对于给定媒体查询的变化。
Demo
import { Component, OnInit, OnDestroy } from '@angular/core'; import { MediaMatcher } from '@angular/cdk/layout'; @Component({ ... }) export class AppComponent implements OnInit, OnDestroy { matcher: MediaQueryList; constructor(public mediaMatcher: MediaMatcher) {} ngOnInit() { this.matcher = this.mediaMatcher.matchMedia('(min-width: 500px)'); this.matcher.addListener(this.myListener); } ngOnDestroy() { this.matcher.removeListener(this.myListener); } myListener(event) { console.log(event.matches ? 'match' : 'no match'); } }
与BreakpointObserver.observe的不同之处在于,MediaMatcher使我们能够访问本机MatchQueryList对象,这在某些情况下可能是必需的。
你可以到Angular CDK Layout API查看相关API。
这里扩展一下在Angular内使用javascript实现同样的方式。
在Angular内是可以直接使用window的,window本身就是有很多方法和属性供我们使用的。
现在我们实现一个在程序加载时判断当前设备是横屏还是竖屏。
Demo 1
import { Component, OnInit } from '@angular/core'; @Component({ ... }) export class AppComponent implements OnInit { isPortrait = false; constructor() {} ngOnInit() { this.isPortrait = window.matchMedia('(orientation: portrait)').matches; if (isPortrait) { consloe.log('This is portrait'); } } }
那我们如何实现初始化时窗口的大小等等呢,看下面的例子。
Demo 2
import { Component, OnInit } from '@angular/core'; @Component({ ... }) export class AppComponent implements OnInit { constructor() {} ngOnInit() { if (window.innerWidth >= 960) { consloe.log('>= 960'); } else { consloe.log('< 960'); } } }
上面我们介绍使用Angular监听窗口的大小变化,下面我们使用另一种方式实现。
Demo 3
import { Component, OnInit, HostListener } from '@angular/core'; @Component({ ... }) export class AppComponent implements OnInit { constructor() {} ngOnInit() { } @HostListener('window:resize') public onWindowResize(): void { if (window.innerWidth >= 960) { consloe.log('>= 960'); } else if (window.innerWidth >= 600 && window.innerWidth < 960) { consloe.log('>= 600 && < 960'); } else { consloe.log('< 600'); } } }
这里当窗口大小发生变化的时候onWindowResize函数会被触发执行,进而实现了实时监听窗口大小变化,然后作出改变。