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 | undefined
  const matches = ref(false)

  const cleanup = () => {
    if (!mediaQuery)
      return
    if ('removeEventListener' in mediaQuery)
      mediaQuery.removeEventListener('change', update)
    else
      mediaQuery.removeListener(update)
  }

  /**
  * update 是 watchEffect的回调,所以其中所有的响应式变量发生变化都会触发update的执行。matches,query
  * 
  */
  const update = () => {
    if (!isSupported.value)
      return

    cleanup()
    
		// 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)
    else
      mediaQuery.addListener(update)
  }
  watchEffect(update)

  // 这个方法内部调用vue3提供的一个方法onScopeDispose。当作用域销毁时,执行回调函数,也就是cleanup
  tryOnScopeDispose(() => cleanup())

  return matches
}

整体来看只做了两件事,监听和取消监听。

  1. 当查询对象发生变化,或者查询结果发生变化,都会重新注册。
  2. 在重新注册的时候,以及effect作用域销毁的时候,取消监听。

你可能感兴趣的:(vueuse源码解析,javascript,前端,vue.js)