Vue3使用hook封裝媒體查詢和事件監(jiān)聽(tīng)的代碼示例
js中媒體查詢的主要方法是使用window對(duì)象下的matchMedia
對(duì)象,查詢語(yǔ)句和CSS媒體查詢一樣。
封裝媒體查詢
首先我們先看監(jiān)聽(tīng)系統(tǒng)主題色的例子
- 首先創(chuàng)建媒體查詢對(duì)象
- 根據(jù)查詢結(jié)果設(shè)置對(duì)應(yīng)的值
- 然后建立監(jiān)聽(tīng)事件,并且在退出時(shí)取消監(jiān)聽(tīng)
export const useTheme = () => { // 首先創(chuàng)建媒體查詢對(duì)象 const themeMedia = matchMedia("(prefers-color-scheme: light)") // 根據(jù)查詢結(jié)果設(shè)置對(duì)應(yīng)的值 const theme = ref(themeMedia.matches ? 'light' : 'dark') const onChange = (e: MediaQueryListEvent) => theme.value = e.matches ? 'light' : 'dark' watchEffect((onCleanup) => { // 然后建立監(jiān)聽(tīng)事件 themeMedia.addEventListener('change', onChange) // 并且在退出時(shí)取消監(jiān)聽(tīng) onCleanup(() => themeMedia.removeEventListener('change', onChange)) }) return theme; }
我們測(cè)試下
const theme = useTheme() watchEffect(() => console.log(theme.value, 'theme'))
如果我們其他查詢查詢,我們需要重新設(shè)置新的值,所以,接下來(lái)我們封裝一個(gè)更通用的媒體查詢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 }
這個(gè)例子里,我們不再對(duì)特定的媒體查詢值做處理,同時(shí),我們將查詢語(yǔ)句作為動(dòng)態(tài)變量,將結(jié)果處理交給開(kāi)發(fā)者。
我們使用通用的hook重寫(xiě)監(jiān)聽(tīng)系統(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)聽(tīng)
接下來(lái),我們?cè)倏吹诙€(gè)簡(jiǎn)單的例子,監(jiān)聽(tīng)網(wǎng)絡(luò)狀態(tài)。
監(jiān)聽(tīng)網(wǎng)絡(luò)狀態(tài),主要通過(guò)監(jiān)聽(tīng)navigator.onLine
的變化,值的變化可以通過(guò)addEventListener方法,
有了封裝媒體查詢的例子,我們首先會(huì)想到封裝事件監(jiān)聽(tīng)的值的變化可以通過(guò)addEventListener方法,成為一個(gè)通用的鉤子函數(shù)。如下:
export const useEventListener = <K extends keyof WindowEventMap>( target: K, listener: (ev: WindowEventMap[K]) => any ) => { watchEffect((onCleanup) => { addEventListener(target, listener) onCleanup(() => removeEventListener(target, listener)) }) }
此時(shí),我們就可以這樣封裝監(jiān)聽(tīng)網(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 }
我們測(cè)試下
const isOnLine = useNetWork() watchEffect(() => console.log(isOnLine.value, 'isOnLine')) <h1 v-if="isOnLine">onLine</h1> <h1 v-else>offLine</h1>
接下來(lái)我們測(cè)試下其他的監(jiān)聽(tīng)事件,比如監(jiān)聽(tīng)scroll事件。
useEventListener('scroll', () => console.log('scroll'))
功能是正常的,但是順理成章,我們還需要寫(xiě)一個(gè)防抖函數(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))
好了今天的分享到這了,如果文章中有紕漏的地方歡迎指正,我及時(shí)修改,感謝你的閱讀
以上就是Vue3使用hook封裝媒體查詢和事件監(jiān)聽(tīng)的代碼示例的詳細(xì)內(nèi)容,更多關(guān)于Vue3 hook封裝媒體查詢和事件監(jiān)聽(tīng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue3中使用scss加上scoped導(dǎo)致樣式失效問(wèn)題
這篇文章主要介紹了vue3中使用scss加上scoped導(dǎo)致樣式失效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10詳解element-ui日期時(shí)間選擇器的日期格式化問(wèn)題
這篇文章主要介紹了詳解element-ui日期時(shí)間選擇器的日期格式化問(wèn)題,本文用到了DateTimePicker來(lái)選擇日期時(shí)間,但是在將數(shù)據(jù)傳回后臺(tái)的過(guò)程中遇到了一些令人頭疼的問(wèn)題,有興趣的一起來(lái)了解一下2019-04-04開(kāi)啟Vue項(xiàng)目缺少node_models包的問(wèn)題及解決
這篇文章主要介紹了開(kāi)啟Vue項(xiàng)目缺少node_models包的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09解決Vue axios post請(qǐng)求,后臺(tái)獲取不到數(shù)據(jù)的問(wèn)題方法
今天小編就為大家分享一篇解決Vue axios post請(qǐng)求,后臺(tái)獲取不到數(shù)據(jù)的問(wèn)題方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08vuex之this.$store.dispatch()與this.$store.commit()的區(qū)別及說(shuō)明
這篇文章主要介紹了vuex之this.$store.dispatch()與this.$store.commit()的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06