Vue3使用hook封裝媒體查詢和事件監(jiān)聽的代碼示例
js中媒體查詢的主要方法是使用window對象下的matchMedia對象,查詢語句和CSS媒體查詢一樣。
封裝媒體查詢
首先我們先看監(jiān)聽系統(tǒng)主題色的例子
- 首先創(chuàng)建媒體查詢對象
- 根據(jù)查詢結(jié)果設(shè)置對應(yīng)的值
- 然后建立監(jiān)聽事件,并且在退出時取消監(jiān)聽
export const useTheme = () => {
// 首先創(chuàng)建媒體查詢對象
const themeMedia = matchMedia("(prefers-color-scheme: light)")
// 根據(jù)查詢結(jié)果設(shè)置對應(yīng)的值
const theme = ref(themeMedia.matches ? 'light' : 'dark')
const onChange = (e: MediaQueryListEvent) => theme.value = e.matches ? 'light' : 'dark'
watchEffect((onCleanup) => {
// 然后建立監(jiān)聽事件
themeMedia.addEventListener('change', onChange)
// 并且在退出時取消監(jiān)聽
onCleanup(() => themeMedia.removeEventListener('change', onChange))
})
return theme;
}我們測試下
const theme = useTheme() watchEffect(() => console.log(theme.value, 'theme'))

如果我們其他查詢查詢,我們需要重新設(shè)置新的值,所以,接下來我們封裝一個更通用的媒體查詢hook,如下,
export const useMatchMedia = (query: string) => {
const themeMedia = matchMedia(query)
const match = ref(themeMedia.matches)
const onChange = (e: MediaQueryListEvent) => match.value = e.matches
watchEffect((onCleanup) => {
themeMedia.addEventListener('change', onChange)
onCleanup(() => themeMedia.removeEventListener('change', onChange))
})
return match
}這個例子里,我們不再對特定的媒體查詢值做處理,同時,我們將查詢語句作為動態(tài)變量,將結(jié)果處理交給開發(fā)者。
我們使用通用的hook重寫監(jiān)聽系統(tǒng)主題色的hook,如下:
export const useTheme = () => {
const theme = useMatchMedia("(prefers-color-scheme: light)")
const theme = ref(themeMedia.matches ? 'light' : 'dark')
return theme ? 'light' : 'dark'
}是不是這樣更簡潔了。
封裝事件監(jiān)聽
接下來,我們再看第二個簡單的例子,監(jiān)聽網(wǎng)絡(luò)狀態(tài)。
監(jiān)聽網(wǎng)絡(luò)狀態(tài),主要通過監(jiān)聽navigator.onLine的變化,值的變化可以通過addEventListener方法,
有了封裝媒體查詢的例子,我們首先會想到封裝事件監(jiān)聽的值的變化可以通過addEventListener方法,成為一個通用的鉤子函數(shù)。如下:
export const useEventListener = <K extends keyof WindowEventMap>(
target: K,
listener: (ev: WindowEventMap[K]) => any
) => {
watchEffect((onCleanup) => {
addEventListener(target, listener)
onCleanup(() => removeEventListener(target, listener))
})
}此時,我們就可以這樣封裝監(jiān)聽網(wǎng)絡(luò)狀態(tài)的hook了
export const useNetWork = () => {
const isOnLine = ref(navigator.onLine)
const setOnLine = () => isOnLine.value = true
const setOffLine = () => isOnLine.value = false
useEventListener('online', setOnLine)
useEventListener('offline', setOffLine)
return isOnLine
}我們測試下
const isOnLine = useNetWork() watchEffect(() => console.log(isOnLine.value, 'isOnLine')) <h1 v-if="isOnLine">onLine</h1> <h1 v-else>offLine</h1>

接下來我們測試下其他的監(jiān)聽事件,比如監(jiān)聽scroll事件。
useEventListener('scroll', () => console.log('scroll'))
功能是正常的,但是順理成章,我們還需要寫一個防抖函數(shù)
export const debounce = (
fn: (...args: any[]) => void,
delay: number
) => {
let timer: NodeJS.Timeout
return (...args: any[]) => {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}useEventListener('scroll', debounce(() => console.log('scroll'), 200))
好了今天的分享到這了,如果文章中有紕漏的地方歡迎指正,我及時修改,感謝你的閱讀
以上就是Vue3使用hook封裝媒體查詢和事件監(jiān)聽的代碼示例的詳細內(nèi)容,更多關(guān)于Vue3 hook封裝媒體查詢和事件監(jiān)聽的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue3中使用scss加上scoped導(dǎo)致樣式失效問題
這篇文章主要介紹了vue3中使用scss加上scoped導(dǎo)致樣式失效問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10
解決Vue axios post請求,后臺獲取不到數(shù)據(jù)的問題方法
今天小編就為大家分享一篇解決Vue axios post請求,后臺獲取不到數(shù)據(jù)的問題方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08
vuex之this.$store.dispatch()與this.$store.commit()的區(qū)別及說明
這篇文章主要介紹了vuex之this.$store.dispatch()與this.$store.commit()的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06

