Angular Material 18+ 高级教程 – 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}`);
逛源码
调用 _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 个区别:
-
次数不同
isMatched 只判断当前 viewport 一次,而 observe 会一直监听 viewport (resize),然后每一次重新判断。
因此 isMatched 返回的是 boolean,而 observe 返回的是可监听的 RxJS Observable。 -
返回的 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 18+ 高级教程 – CDK Portal
下一篇 Angular Material 18+ 高级教程 – CDK Scrolling
想查看目录,请移步 Angular 18+ 高级教程 – 目录
喜欢请点推荐👍,若发现教程内容以新版脱节请评论通知我。happy coding 😊💻