十個(gè)有用的自定義Vue鉤子函數(shù)總結(jié)
Vue 是我使用的第一個(gè) JS 框架??梢哉f(shuō),Vue 是我進(jìn)入JavaScript世界的第一道門之一。目前,Vue 仍然是一個(gè)很棒的框架。隨著 composition API 的出現(xiàn),Vue 只會(huì)有更大的發(fā)展。在這篇文章中,我將介紹 10 個(gè)有用的自定義鉤子,讓我們的代碼更加好看。
useWindowResize
這是一個(gè)基本的鉤子,因?yàn)樗挥迷诤芏囗?xiàng)目中.
import { ref, onMounted, onUnmounted } from 'vue';
export function useWindowResize() {
const width = ref(window.innerWidth);
const height = ref(window.innerHeight);
const handleResize = () => {
width.value = window.innerWidth;
height.value = window.innerHeight;
}
onMounted(() => {
window.addEventListener('resize', handleResize)
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
})
return {
width,
height
}
}使用就更簡(jiǎn)單了,只需要調(diào)用這個(gè)鉤子就可以獲得 window 的寬度和高度。
setup() {
const { width, height } = useWindowResize();
}useStorage
你想通過(guò)在 session storage 或 local storage 中存儲(chǔ)數(shù)據(jù)的值來(lái)持久化數(shù)據(jù),并將該值綁定到視圖?有了一個(gè)簡(jiǎn)單的鉤子--useStorage,這將變得非常容易。我們只需要?jiǎng)?chuàng)建一個(gè)鉤子來(lái)返回從存儲(chǔ)空間得到的數(shù)據(jù),以及一個(gè)函數(shù)來(lái)在我們想要改變數(shù)據(jù)時(shí)將其存儲(chǔ)在存儲(chǔ)空間。下面是我的鉤子。
import { ref } from 'vue';
const getItem = (key, storage) => {
let value = storage.getItem(key);
if (!value) {
return null;
}
try {
return JSON.parse(value)
} catch (error) {
return value;
}
}
export const useStorage = (key, type = 'session') => {
let storage = null;
switch (type) {
case 'session':
storage = sessionStorage;
break;
case 'local':
storage = localStorage;
break;
default:
return null;
}
const value = ref(getItem(key, storage));
const setItem = (storage) => {
return (newValue) => {
value.value = newValue;
storage.setItem(key, JSON.stringify(newValue));
}
}
return [
value,
setItem(storage)
]
}在我的代碼中,我使用 JSON.parse ** 和 JSON.stringify** 來(lái)格式化數(shù)據(jù)。如果你不想格式化它,你可以刪除它。下面是一個(gè)如何使用這個(gè)鉤子的例子。
const [token, setToken] = useStorage('token');
setToken('new token');useNetworkStatus
這是一個(gè)有用的鉤子,支持檢查網(wǎng)絡(luò)連接的狀態(tài)。為了實(shí)現(xiàn)這個(gè)鉤子,我們需要為事件 "在線"和 "離線"添加事件監(jiān)聽(tīng)器。在事件中,我們只是調(diào)用一個(gè)回調(diào)函數(shù),參數(shù)為網(wǎng)絡(luò)狀態(tài)。下面是我的代碼。
import { onMounted, onUnmounted } from 'vue';
export const useNetworkStatus = (callback = () => { }) => {
const updateOnlineStatus = () => {
const status = navigator.onLine ? 'online' : 'offline';
callback(status);
}
onMounted(() => {
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOnlineStatus);
});
onUnmounted(() => {
window.removeEventListener('online', updateOnlineStatus);
window.removeEventListener('offline', updateOnlineStatus);
})
}調(diào)用方式:
useNetworkStatus((status) => {
console.log(`Your network status is ${status}`);
}useCopyToClipboard
剪切板是一個(gè)比較常見(jiàn)的功能,我們也可以將它封裝成 hook,代碼如下所示:
function copyToClipboard(text) {
let input = document.createElement('input');
input.setAttribute('value', text);
document.body.appendChild(input);
input.select();
let result = document.execCommand('copy');
document.body.removeChild(input);
return result;
}
export const useCopyToClipboard = () => {
return (text) => {
if (typeof text === "string" || typeof text == "number") {
return copyToClipboard(text);
}
return false;
}
}使用如下:
const copyToClipboard = useCopyToClipboard();
copyToClipboard('just copy');useTheme
只是一個(gè)簡(jiǎn)短的鉤子來(lái)改變網(wǎng)站的主題。它可以幫助我們輕松地切換網(wǎng)站的主題,只需用主題名稱調(diào)用這個(gè)鉤子。下面是一個(gè)我用來(lái)定義主題變量的CSS代碼例子。
html[theme="dark"] {
--color: #FFF;
--background: #333;
}
html[theme="default"], html {
--color: #333;
--background: #FFF;
}要改變主題,只需要做一個(gè)自定義的鉤子,它返回一個(gè)函數(shù)來(lái)通過(guò)主題名稱改變主題。代碼如下:
export const useTheme = (key = '') => {
return (theme) => {
document.documentElement.setAttribute(key, theme);
}
}使用如下:
const changeTheme = useTheme();
changeTheme('dark');usePageVisibility
有時(shí),當(dāng)客戶不專注于我們的網(wǎng)站時(shí),我們需要做一些事情。要做到這一點(diǎn),我們需要一些東西,讓我們知道用戶是否在關(guān)注。這是一個(gè)自定義的鉤子。我把它叫做 PageVisibility,代碼如下:
import { onMounted, onUnmounted } from 'vue';
export const usePageVisibility = (callback = () => { }) => {
let hidden, visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
const handleVisibilityChange = () => {
callback(document[hidden]);
}
onMounted(() => {
document.addEventListener(visibilityChange, handleVisibilityChange, false);
});
onUnmounted(() => {
document.removeEventListener(visibilityChange, handleVisibilityChange);
});
}用法如下:
usePageVisibility((hidden) => {
console.log(`User is${hidden ? ' not' : ''} focus your site`);
});useViewport
有時(shí)我們會(huì)用寬度來(lái)檢測(cè)當(dāng)前的用戶設(shè)備,這樣我們就可以根據(jù)設(shè)備來(lái)處理對(duì)應(yīng)的內(nèi)容。這種場(chǎng)景,我們也可以封裝成一個(gè) hook,代碼如下:
import { ref, onMounted, onUnmounted } from 'vue';
export const MOBILE = 'MOBILE'
export const TABLET = 'TABLET'
export const DESKTOP = 'DESKTOP'
export const useViewport = (config = {}) => {
const { mobile = null, tablet = null } = config;
let mobileWidth = mobile ? mobile : 768;
let tabletWidth = tablet ? tablet : 922;
let device = ref(getDevice(window.innerWidth));
function getDevice(width) {
if (width < mobileWidth) {
return MOBILE;
} else if (width < tabletWidth) {
return TABLET;
}
return DESKTOP;
}
const handleResize = () => {
device.value = getDevice(window.innerWidth);
}
onMounted(() => {
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});
return {
device
}
}使用如下:
const { device } = useViewport({ mobile: 700, table: 900 });useOnClickOutside
當(dāng) model 框彈出時(shí),我們希望能點(diǎn)擊其它區(qū)域關(guān)閉它,這個(gè)可以使用 clickOutSide,這種場(chǎng)景我們也可以封裝成鉤子,代碼如下:
import { onMounted, onUnmounted } from 'vue';
export const useOnClickOutside = (ref = null, callback = () => {}) => {
function handleClickOutside(event) {
if (ref.value && !ref.value.contains(event.target)) {
callback()
}
}
onMounted(() => {
document.addEventListener('mousedown', handleClickOutside);
})
onUnmounted(() => {
document.removeEventListener('mousedown', handleClickOutside);
});
}用法如下:
<template>
<div ref="container">View</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const container = ref(null);
useOnClickOutside(container, () => {
console.log('Clicked outside');
})
}
}
</script>useScrollToBottom
除了分頁(yè)列表,加載更多(或懶惰加載)是一種友好的加載數(shù)據(jù)的方式。特別是對(duì)于移動(dòng)設(shè)備,幾乎所有運(yùn)行在移動(dòng)設(shè)備上的應(yīng)用程序都在其用戶界面中應(yīng)用了load more。要做到這一點(diǎn),我們需要檢測(cè)用戶滾動(dòng)到列表底部,并為該事件觸發(fā)一個(gè)回調(diào)。
useScrollToBottom 是一個(gè)有用的鉤子,支持你這樣做。代碼如下:
import { onMounted, onUnmounted } from 'vue';
export const useScrollToBottom = (callback = () => { }) => {
const handleScrolling = () => {
if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
callback();
}
}
onMounted(() => {
window.addEventListener('scroll', handleScrolling);
});
onUnmounted(() => {
window.removeEventListener('scroll', handleScrolling);
});
}用法如下:
useScrollToBottom(() => { console.log('Scrolled to bottom') })useTimer
useTimer 的代碼比其他鉤子要長(zhǎng)一些。useTimer 支持運(yùn)行一個(gè)帶有一些選項(xiàng)的定時(shí)器,如開始、暫停/恢復(fù)、停止。要做到這一點(diǎn),我們需要使用 setInterval 方法。在這里,我們需要檢查定時(shí)器的暫停狀態(tài)。如果定時(shí)器沒(méi)有暫停,我們只需要調(diào)用一個(gè)回調(diào)函數(shù),該函數(shù)由用戶作為參數(shù)傳遞。為了支持用戶了解該定時(shí)器當(dāng)前的暫停狀態(tài),除了action useTimer之外,還要給他們一個(gè)變量 isPaused,其值為該定時(shí)器的暫停狀態(tài)。代碼如下:
import { ref, onUnmounted } from 'vue';
export const useTimer = (callback = () => { }, step = 1000) => {
let timerVariableId = null;
let times = 0;
const isPaused = ref(false);
const stop = () => {
if (timerVariableId) {
clearInterval(timerVariableId);
timerVariableId = null;
resume();
}
}
const start = () => {
stop();
if (!timerVariableId) {
times = 0;
timerVariableId = setInterval(() => {
if (!isPaused.value) {
times++;
callback(times, step * times);
}
}, step)
}
}
const pause = () => {
isPaused.value = true;
}
const resume = () => {
isPaused.value = false;
}
onUnmounted(() => {
if (timerVariableId) {
clearInterval(timerVariableId);
}
})
return {
start,
stop,
pause,
resume,
isPaused
}
}用法如下:
function handleTimer(round) {
roundNumber.value = round;
}
const {
start,
stop,
pause,
resume,
isPaused
} = useTimer(handleTimer);以上就是十個(gè)有用的自定義Vue鉤子函數(shù)總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Vue鉤子函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vscode中Vue別名路徑提示的實(shí)現(xiàn)
這篇文章主要介紹了vscode中Vue別名路徑提示的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
Vue3?Transition組件給頁(yè)面切換并加上動(dòng)畫效果
這篇文章主要給大家介紹了關(guān)于Vue3?Transition組件給頁(yè)面切換并加上動(dòng)畫效果的相關(guān)資料,vue的過(guò)渡動(dòng)畫主要是transition標(biāo)簽的使用,配合css動(dòng)畫實(shí)現(xiàn)的,需要的朋友可以參考下2023-06-06
vue實(shí)現(xiàn)ajax滾動(dòng)下拉加載,同時(shí)具有l(wèi)oading效果(推薦)
這篇文章主要介紹了vue實(shí)現(xiàn)ajax滾動(dòng)下拉加載,同時(shí)具有l(wèi)oading效果的實(shí)現(xiàn)代碼,文章包括難點(diǎn)說(shuō)明,介紹的非常詳細(xì),感興趣的朋友參考下2017-01-01
ant design vue嵌套表格及表格內(nèi)部編輯的用法說(shuō)明
這篇文章主要介紹了ant design vue嵌套表格及表格內(nèi)部編輯的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
解決echarts圖表使用v-show控制圖表顯示不全的問(wèn)題
這篇文章主要介紹了解決echarts圖表使用v-show控制圖表顯示不全的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
解決echarts vue數(shù)據(jù)更新,視圖不更新問(wèn)題(echarts嵌在vue彈框中)
這篇文章主要介紹了解決echarts vue數(shù)據(jù)更新,視圖不更新問(wèn)題(echarts嵌在vue彈框中),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07

