创建自定义Vue Hooks可以帮助我们更好地复用代码和逻辑。以下是10个自定义Vue Hook的实例,每个都有其特定的用途:
创建自定义Vue Hooks可以帮助我们更好地复用代码和逻辑。以下是10个自定义Vue Hook的实例,每个都有其特定的用途:
useDebounce - 防抖函数Hook
import { ref } from 'vue';
export function useDebounce(value, delay = 500) {
let timeout;
const debouncedValue = ref(value);
const setDebouncedValue = (newValue) => {
clearTimeout(timeout);
timeout = setTimeout(() => {
debouncedValue.value = newValue;
}, delay);
};
return [debouncedValue, setDebouncedValue];
}
useThrottle - 节流函数Hook
import { ref } from 'vue';
export function useThrottle(value, delay = 500) {
let timeout;
const throttledValue = ref(value);
const setThrottledValue = (newValue) => {
if (!timeout) {
timeout = setTimeout(() => {
throttledValue.value = newValue;
timeout = null;
}, delay);
}
};
return [throttledValue, setThrottledValue];
}
useEventListener - 事件监听Hook
import { onMounted, onUnmounted } from 'vue';
export function useEventListener(event, handler, options = false) {
onMounted(() => {
window.addEventListener(event, handler, options);
});
onUnmounted(() => {
window.removeEventListener(event, handler, options);
});
}
useMousePosition - 追踪鼠标位置的Hook
import { ref, onMounted, onUnmounted } from 'vue';
export function useMousePosition() {
const x = ref(0);
const y = ref(0);
const updateMousePosition = (event) => {
x.value = event.clientX;
y.value = event.clientY;
};
onMounted(() => {
window.addEventListener('mousemove', updateMousePosition);
});
onUnmounted(() => {
window.removeEventListener('mousemove', updateMousePosition);
});
return { x, y };
}
使用方法:
<template>
<div>
<p>X: {{ x }}</p>
<p>Y: {{ y }}</p>
</div>
</template>
<scriptlang="ts">
importuseMousePosition from'@/hooks/useMousePosition'
const{ x, y } = useMousePosition();
</script>
useKeyPress - 键盘按键Hook
import { ref } from 'vue';
export function useKeyPress(targetKey) {
const keyPressed = ref(false);
window.addEventListener('keydown', (event) => {
if (event.key === targetKey) {
keyPressed.value = true;
}
});
window.addEventListener('keyup', () => {
keyPressed.value = false;
});
return keyPressed;
}
useFetch - 用于执行API请求并处理响应
import { ref } from 'vue';
import axios from 'axios';
export function useFetch(url) {
const data = ref(null);
const isLoading = ref(true);
const error = ref(null);
const fetchData = async () => {
try {
const response = await axios.get(url);
data.value = response.data;
} catch (err) {
error.value = err.message;
} finally {
isLoading.value = false;
}
};
fetchData();
return { data, isLoading, error };
}
使用方法:
import { useFetch } from './useFetch.js';
const { data, isLoading, error } = useFetch('https://api.example.com/data');
useToggle - 用于在组件中创建一个切换状态
import { ref } from 'vue';
export function useToggle(defaultValue = false) {
const toggled = ref(defaultValue);
const toggle = () => {
toggled.value = !toggled.value;
};
return { toggled, toggle };
}
使用方法:
import { useToggle } from './useToggle.js';
const { toggled, toggle } = useToggle(true);
useDebounce - 防抖函数,限制函数的调用频率
export function useDebounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
使用方法:
import { useDebounce } from './useDebounce.js';
const debouncedFunction = useDebounce(() => {
console.log('Debounced function called!');
}, 500);
debouncedFunction();
useMediaQuery - 响应媒体查询变化
import { ref, onUnmounted } from 'vue';
export function useMediaQuery(query) {
const matches = ref(false);
const media = window.matchMedia(query);
if (media.matches) matches.value = true;
const listener = () => {
matches.value = media.matches;
};
media.addEventListener('change', listener);
onUnmounted(() => {
media.removeEventListener('change', listener);
});
return matches;
}
使用方法:
import { useMediaQuery } from './useMediaQuery.js';
const isDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
useLocalStorage - 用于与本地存储交互
import { ref } from 'vue';
export function useLocalStorage(key, initialValue) {
const value = ref(initialValue);
value.value = localStorage.getItem(key) || initialValue;
const set = (newValue) => {
value.value = newValue;
localStorage.setItem(key, newValue);
};
return [value, set];
}
使用方法:
import { useLocalStorage } from './useLocalStorage.js';
const [storedValue, setStoredValue] = useLocalStorage('myKey', 'initialValue');
useInterval - 封装 setInterval 和 clearInterval
import { ref, onUnmounted } from 'vue';
export function useInterval(callback, interval = 1000) {
const timer = ref(null);
const start = () => {
if (timer.value) return;
timer.value = setInterval(callback, interval);
};
const stop = () => {
if (!timer.value) return;
clearInterval(timer.value);
timer.value = null;
};
onUnmounted(stop);
return { start, stop };
}
使用方法:
import { useInterval } from './useInterval.js';
const { start, stop } = useInterval(() => {
console.log('Interval triggered!');
}, 2000);
start(); // 开始
// 组件卸载时自动停止
useDownload - 数据导出
import {
ElNotification
}
from 'element-plus'
/**
* @description 接收数据流生成 blob,创建链接,下载文件
* @param {any} data 导出的文件blob数据 (必传)
* @param {String} tempName 导出的文件名 (必传)
* @param {Boolean} isNotify 是否有导出消息提示 (默认为 true)
* @param {String} fileType 导出的文件格式 (默认为.xlsx)
* */
interfaceuseDownloadParam {
data: any;
tempName: string;
isNotify ? : boolean;
fileType ? : string;
}
exportconstuseDownload = async ({
data,
tempName,
isNotify = true,
fileType = '.xlsx',
}: useDownloadParam) => {
if (isNotify) {
ElNotification({
title: '温馨提示',
message: '如果数据庞大会导致下载缓慢哦,请您耐心等待!',
type: 'info',
duration: 3000,
})
}
try {
constblob = newBlob([data])
// 兼容 edge 不支持 createObjectURL 方法
if ('msSaveOrOpenBlob' innavigator)
returnwindow.navigator.msSaveOrOpenBlob(blob, tempName + fileType)
constblobUrl = window.URL.createObjectURL(blob)
constexportFile = document.createElement('a')
exportFile.style.display = 'none'
exportFile.download = `${tempName}${fileType}`
exportFile.href = blobUrl
document.body.appendChild(exportFile)
exportFile.click()
// 去除下载对 url 的影响
document.body.removeChild(exportFile)
window.URL.revokeObjectURL(blobUrl)
} catch (error) {
console.log(error)
}
}
使用方法:
import{
useDownload
}
from "@/hooks/useDownload";
constuserForm = reactive({})
constuserListExport = () => {
newPromise(resolve => {
$Request({
url: $Urls.userListExport,
method: "post",
data: userForm,
responseType: "blob"
}).then((res: any) => {
useDownload({
data: res.data,
tempName: "用户列表"
});
resolve(res);
});
});
};
推荐几个HOOKS库
- vueuse
- ahooks
- v3u/hooks
- logaretm/vue-use-web