十個有用的 Vue.js 自定義 Hook
Vue.js 是我使用的第一個 JavaScript 框架。 我可以說 Vue.js 是我進入 JavaScript 世界的第一扇門之一。
目前,Vue.js 仍然是一個很棒的框架。 我認為有了組合 API,Vue.js 只會增長得更多。 在本文中,我將向分享 10 個可以使用 Vue.js 制作的有用的自定義鉤hook。
01、使用窗口調整大小
這是一個基本的hook。 因為它在許多項目中使用,并且使用純 JavaScript 或任何框架構建它太容易了。
與 Vue 相同,只需幾行代碼即可構建它。
這是我的代碼:
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
}
}
不僅構建簡單,而且使用起來也很容易。 只需要調用這個鉤子即可獲取窗口的寬度和高度:
setup() {
const { width, height } = useWindowResize();
}
02、使用存儲
您想通過將數(shù)據值存儲在會話存儲或本地存儲中并將該值綁定到視圖來持久保存數(shù)據嗎? 只需一個簡單的hook——useStorage,一切就變得如此簡單。
我們只需要創(chuàng)建一個hook,返回從存儲中獲取的數(shù)據,以及一個在我們想要更改數(shù)據時將數(shù)據存儲在存儲中的函數(shù)。
這是我的代碼。
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 來格式化數(shù)據。
如果您不想格式化它,可以將其刪除。 這是如何使用此hook的示例。
const [token, setToken] = useStorage('token');
setToken('new token');
03、使用網絡狀態(tài)
這是一個有用的hook,支持檢查網絡連接的狀態(tài)。 為了實現(xiàn)這個hook,我們需要為“在線”和“離線”事件添加事件監(jiān)聽器。
在事件中,我們只是調用一個回調函數(shù),參數(shù)為網絡狀態(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);
})
}
只是簡單易用。
目前,我使用參數(shù)“online”/“offline”調用回調函數(shù)。 您可以將其更改為真/假或任何您想要的。
useNetworkStatus((status) => {
console.log(`Your network status is ${status}`);
}
04、使用復制到剪貼板
將文本復制到剪貼板是每個項目中都很流行的功能。 我知道我們可以創(chuàng)建一個函數(shù)來代替鉤子來做到這一點。
但我喜歡數(shù)字 10,所以我決定在這篇文章中加入這個hook。 這個hook非常簡單,只需返回一個支持將文本復制到剪貼板的函數(shù)即可。
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;
}
}
在我的代碼中,我在函數(shù) copyToClipboard 中將邏輯復制文本放入剪貼板。 我知道我們有很多方法可以做到這一點。 你可以在此功能中嘗試最適合你的方法。
至于如何使用,調用即可。
const copyToClipboard = useCopyToClipboard();
copyToClipboard('just copy');
05、使用主題
只需一個簡短的鉤子即可更改網站的主題。 它可以幫助我們輕松切換網站的主題,只需用主題名稱調用此hook即可。 這是我用來定義主題變量的 CSS 代碼示例。
html[theme="dark"] {
--color: #FFF;
--background: #333;
}
html[theme="default"], html {
--color: #333;
--background: #FFF;
}
要更改主題,我們只需要創(chuàng)建一個自定義掛鉤,它將返回一個通過主題名稱更改主題的函數(shù)。
這是我的這個鉤子的代碼:
export const useTheme = (key = '') => {
return (theme) => {
document.documentElement.setAttribute(key, theme);
}
}
而且使用起來太方便了。
const changeTheme = useTheme();
changeTheme('dark');
06、使用頁面可見性
有時,當客戶不關注我們的網站時,我們需要做一些事情。 為此,我們需要一些東西來讓我們知道用戶是否集中注意力。 這是一個定制的hook。
我稱之為 usePageVisibility,下面是該hook的代碼:
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);
});
}
要使用這個hook,我們只需要創(chuàng)建一個帶有客戶端隱藏狀態(tài)(焦點狀態(tài))參數(shù)的回調函數(shù)。
usePageVisibility((hidden) => {
console.log(`User is${hidden ? ' not' : ''} focus your site`);
});
07、使用視口
在第一個自定義hook中,我們構建了useWindowRezie,它可以幫助我們查看窗口的當前寬度和高度。
我認為這對于那些想要構建適用于多種屏幕尺寸的東西的人很有幫助。
在我處理過的案例中,我們經常使用寬度來檢測當前用戶設備。 它可以幫助我們在他們的設備上安裝一些東西。
在此hook中,我將使用 useWindowResize 構建相同的內容,但它返回設備名稱而不是寬度和高度值。
這是這個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
}
}
它是如此容易。 除了默認的設備尺寸之外,當我們使用包含手機和平板電腦尺寸的參數(shù)對象調用該hook時,用戶可以修改它。 這是我們使用它的方式:
const { device } = useViewport({ mobile: 700, table: 900 });
08、使用OnClickOutside
目前,模態(tài)被用于許多應用程序中。 它對于許多用例(表單、確認、警告等)確實很有幫助。
我們經常用它處理的流行操作之一是用戶在模式之外單擊。 useOnClickOutside 對于這種情況是一個有用的hook。
我們只需要一個 ref 元素、回調函數(shù)并將其綁定到窗口事件中。 這是我的代碼(適用于桌面和移動設備):
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);
});
}
正如我所說,要使用它,我們只需要使用參數(shù) ref 元素和回調函數(shù)來調用它。
<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>
09、使用滾動到底部
除了分頁列表之外,加載更多(或延遲加載)是加載數(shù)據的一種友好方式。 特別是對于移動設備,幾乎在移動設備上運行的應用程序都會在其 UI 中加載更多負載。 為此,我們需要檢測用戶滾動到列表底部并觸發(fā)該事件的回調。
useScrollToBottom 是一個有用的hook來支持您這樣做。 這是我構建該hook的代碼:
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);
});
}
在我的hook中,我通過條件“((window.innerHeight + window.scrollY) >= document.body.scrollHeight)”檢測到底部。
我們有很多方法來檢測它。 如果您的項目符合其他條件,我們就使用它們。 以下是如何使用此hook的示例:
useScrollToBottom(() => { console.log('Scrolled to bottom') })
10、使用定時器
最后,我們來到最后一個鉤子。 這個鉤子的代碼比其他鉤子要長一些。 useTimer 將支持我們運行帶有一些選項的計時器,例如開始、暫停/恢復、停止。
為此,我們需要使用 setInterval 方法,在該方法中,我們將推送處理函數(shù)。 在那里,我們需要檢查計時器的暫停狀態(tài)。
如果計時器沒有暫停,我們只需要調用一個回調函數(shù),該函數(shù)由用戶作為參數(shù)傳遞。
為了支持用戶了解該計時器的當前暫停狀態(tài),除了 useTimer 操作之外,還為他們提供一個變量 isPaused ,其值作為計時器的暫停狀態(tài)。
這是我構建該hook的代碼:
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
}
}
這是使用 useTimer hook的一種方法:
function handleTimer(round) {
roundNumber.value = round;
}
const {
start,
stop,
pause,
resume,
isPaused
} = useTimer(handleTimer);
到這里,我已經跟大家分享了10 個有用的 Vue.js hook。 我認為它們的構建和使用都很簡單。 我只是為那些想要在 Vue.js 中使用這些鉤子的人提供一些注釋。
請記住刪除要添加到窗口的事件。 Vue 為我們提供了一個有用的組合 API onUnmounted ,它可以幫助我們在卸載hook之前運行我們的操作。
在我構建的每個鉤子中,我總是刪除 onUnmounted 中的事件偵聽器。
僅在真正需要時才使用反應變量。 如果您想使用一個存儲某些內容的變量,并且希望在數(shù)據更改時同步其數(shù)據,那么,讓我們使用反應式變量。
但如果它只是一個在我們的hook中存儲數(shù)據的變量(計數(shù)器、標志......),我認為你不需要使用反應變量。
如果可以的話,不要在鉤子中進行硬編碼(設置固定值)。
我認為我們只需要將邏輯存儲在我們的hook中。 關于配置值,我們應該讓用戶填寫它(例如:useViewport)。
最后,在我的文章中,我與您分享了10 個有用的 Vue 自定義hook,我希望它們對您有所幫助。 Vue.js 是一個很棒的框架,我希望你可以用它構建更多很棒的東西。