import { onBeforeUnmount, onMounted, ref, type Ref } from 'vue' /** * 响应式地跟踪 CSS 媒体查询匹配状态。 * * SSR 安全:服务端渲染期间始终返回 `false`,避免 hydration mismatch; * 客户端 `onMounted` 之后才订阅 `matchMedia`。 * * @param query - 合法 CSS media query 字符串 * @returns Ref - 当前是否匹配 */ export function useMediaQuery(query: string): Ref { const matches = ref(false) let mql: MediaQueryList | null = null const handler = (e: MediaQueryListEvent) => { matches.value = e.matches } onMounted(() => { if (typeof window === 'undefined' || !window.matchMedia) return mql = window.matchMedia(query) matches.value = mql.matches mql.addEventListener('change', handler) }) onBeforeUnmount(() => { mql?.removeEventListener('change', handler) }) return matches }