3.7 Browser -- useMediaQuery
3.7 Browser – useMediaQuery
https://vueuse.org/core/useMediaQuery/
作用
响应式的媒体查询。一旦你创建了一个MediaQueryList
对象,你就可以得到查询的结果,或者在结果变化时收到通知。
媒体查询我们一般都是用来根据窗口大小,来适配不同的UI。
比如:
@media screen and (max-width: 300px) {body {background-color:lightblue;}
}
官方示例
import { useMediaQuery } from '@vueuse/core'const isLargeScreen = useMediaQuery('(min-width: 1024px)') // 窗口是否是大屏幕(最小宽度1024px)
const isPreferredDark = useMediaQuery('(prefers-color-scheme: dark)') // 窗口是否是黑暗模式
当屏幕大小变化时,isLargeScreen
也会响应式改变。isPreferredDark
也是同样的。
源码分析
比起如何实现,这段代码中,更重要的是知道**“媒体查询”**包括哪些?
export function useMediaQuery(query: MaybeComputedRef<string>, options: ConfigurableWindow = {}) {const { window = defaultWindow } = options// window.matchMedia 和 @media是等效的const isSupported = useSupported(() => window && 'matchMedia' in window && typeof window.matchMedia === 'function')let mediaQuery: MediaQueryList | undefinedconst matches = ref(false)const cleanup = () => {if (!mediaQuery)returnif ('removeEventListener' in mediaQuery)mediaQuery.removeEventListener('change', update)elsemediaQuery.removeListener(update)}/*** update 是 watchEffect的回调,所以其中所有的响应式变量发生变化都会触发update的执行。matches,query* */const update = () => {if (!isSupported.value)returncleanup()// matchMedia() 返回一个新的 MediaQueryList 对象,表示指定的媒体查询字符串解析后的结果// 包括两个属性:1 media:查询语句的内容; 2 matches:用于检测查询结果mediaQuery = window!.matchMedia(resolveRef(query).value)matches.value = mediaQuery.matches// 根据mediaQuery支持的方法来注册监听。if ('addEventListener' in mediaQuery)mediaQuery.addEventListener('change', update)elsemediaQuery.addListener(update)}watchEffect(update)// 这个方法内部调用vue3提供的一个方法onScopeDispose。当作用域销毁时,执行回调函数,也就是cleanuptryOnScopeDispose(() => cleanup())return matches
}
整体来看只做了两件事,监听和取消监听。
- 当查询对象发生变化,或者查询结果发生变化,都会重新注册。
- 在重新注册的时候,以及
effect
作用域销毁的时候,取消监听。