Angular Material 17+ 高级教程 – CDK Layout の Breakpoints

前言

CDK Layout 主要是用于处理 Breakpoints,它底层是依靠 window.matchMedia 来实现的。

 

Material Design 2 & 3 Breakpoints

Material Design 有对 Breakpoints 的规范,Angular CDK 依照的是 Material Design 2。

相关源码在 breakpoints.ts

没什么特别的,它就只是一个 Definition,不同 Viewport Size / Device 对应不同的 Media Query。

如果我们不喜欢 Material Design 2 的规范,我们自己也可以 Define 一个 Material Design 3 的 Breakpoints

export const M3Breakpoints = {
  Compact: '(max-width: 599.98px)',
  Medium: '(min-width: 600px) and (max-width: 839.98px)',
  Expanded: '(min-width: 840px) and (max-width: 1199.98px)',
  Large: '(min-width: 1200px) and (max-width: 1599.98px)',
  Extralarge: '(min-width: 1600px)',

  PhoneInPortrait: '(max-width: 599.98px)',
  TabletInPortrait: '(min-width: 600px) and (max-width: 839.98px)',

  PhoneInLandscape: '(min-width: 840px) and (max-width: 1199.98px)',
  TabletInLandscape: '(min-width: 840px) and (max-width: 1199.98px)',
  
  DesktopSmall: '(min-width: 840px) and (max-width: 1199.98px)',
  DesktopMedium: '(min-width: 1200px) and (max-width: 1599.98px)',
  DesktopLarge: '(min-width: 1600px)',
};

 

MediaMatcher

MediaMatcher 是一个 Root Level Injector Service Provider。

它是 Angular CDK 对 window.mediaMatch 的封装。

源码在 media-matcher.ts

使用方式

export class AppComponent {
  constructor() {

    // 1. inject MediaMatcher
    const mediaMatcher = inject(MediaMatcher);

    // 2. match media query
    const mediaQueryList = mediaMatcher.matchMedia('(max-width: 599.98px)');

    // 3. 使用 MediaQueryList
    const isMatched = mediaQueryList.matches;
    mediaQueryList.addEventListener('change', () => {});
  }
}

和 window.matchMedia 用法一模一样。

 

BreakpointObserver

BreakpointObserver 是一个 Root Level Injector Service Provider。

isMatched 方法

BreakpointObserver.isMatched 方法可以判断当前的 viewport 是否满足特定的 media query。

export class AppComponent {
  constructor() {
    // 1. inject BreakpointObserver
    const breakpointObserver = inject(BreakpointObserver);

    // 2. 判断当前 viewport 是否满足 media query
    const matched1 = breakpointObserver.isMatched('(max-width: 599.98px)');

    // 3. 判断当前 viewport 是否满足 Material Design 2 XSmall media query
    const matched2 = breakpointObserver.isMatched(Breakpoints.XSmall); 

    // 4. 判断当前 viewport 是否满足 Material Design 3 Compact media query
    const matched3 = breakpointObserver.isMatched(M3Breakpoints.Compact); 
  }
}

isMatched 还支持 multiple media query,只要其中一个 matched 就算 matched。

const matched3 = breakpointObserver.isMatched(
  [
    M3Breakpoints.Compact, 
    M3Breakpoints.Medium
  ]
);

传入一个 array 就可以了。

或者用 string join by 逗号也行

const matched5 = breakpointObserver.isMatched(`${M3Breakpoints.Compact}, ${M3Breakpoints.Medium}`); 

逛源码

源码在 breakpoints-observer.ts

调用 _regsiterQuery 方法然后拿 mql.matches,我们继续看 mql 是什么

_regsiterQuery 方法

简而言之

const matched1 = breakpointObserver.isMatched('(max-width: 599.98px)');
const matched2 = window.matchMedia('(max-width: 599.98px)').matches;

这 2 句是等价的。

observe 方法

constructor() {
  // 1. inject BreakpointObserver
  const breakpointObserver = inject(BreakpointObserver);
  
  // 2. 监听 media query
  breakpointObserver.observe(
    [
      M3Breakpoints.Compact, 
      M3Breakpoints.Medium
    ]
  ).subscribe(({ breakpoints, matches }) => {
      console.log('breakpoints', breakpoints);
      console.log('matches', matches);
  });
}

效果

observe 和 isMatched 用法大同小异,只有 2 个区别:

  1. 次数不同

    isMatched 只判断当前 viewport 一次,而 observe 会一直监听 viewport (resize),然后每一次重新判断。

    因此 isMatched 返回的是 boolean,而 observe 返回的是可监听的 RxJS Observable。
  2. 返回的 result 不同

    当有你有 multiple media query 时,

    isMatched 只能告诉你整体是 matched or not matched,你无法知道具体是哪一个 media query matched。

    observe 除了告诉你整体是 matched or not matched,它还会返回一个对象,里面的 key 是 media query,value 是表示这个 media query 有没有 matched。

observe 源码我们就不逛,它底层实现方式是 window.matchMedia + addEventListener(''change),上一 part 逛源码时已经有看到一点了。

另外,subscribe observe 返回的 Observable 会立马触发一次,获得当下 viewport match media query result,这点和 window.matchMedia + addEventListener(''change) 不同哦。

 

总结

虽然它们只是对 window.matchMedia 的小封装,但还是鼓励大家用,尽量不要直接依赖 window 是顺风水的。

 

 

目录

上一篇 Angular Material 17+ 高级教程 – CDK Portal

下一篇 Angular Material 17+ 高级教程 – CDK Scrolling

想查看目录,请移步 Angular 17+ 高级教程 – 目录

posted @ 2024-02-29 00:17  兴杰  阅读(23)  评论(0编辑  收藏  举报