vue3 Hooks函数使用及常用utils封装
hooks 是什么
vue3使用了composition API,我们可自定义封装hooks,达到复用,在Vue2中采取的mixins,对mixins而言, hooks更清楚复用功能代码的来源, 更清晰易懂。
简单来说:hooks 就是函数的一种写法,就是将文件的一些单独功能的 js 代码进行抽离出来进行封装使用
自定义 hook 需要满足的规范
具备可复用功能,才需要抽离为 hooks 独立文件
函数名前缀加上use开头,形如: useXX
合理利用Vue提供的响应式函数及生命周期
暴露出 变量 或 方法 提供外部需要时使用
Hooks 常用 工具
src/hooks/index.ts
倒计时hooks
import { ref, Ref, onBeforeMount } from 'vue';
/**
* 倒计时hooks
* @param {Number} second 倒计时秒数
* @return {Number} count 倒计时秒数
* @return {Function} countDown 倒计时函数
* @example
* const { count, countDown } = useCountDown()
* countDown(60)
* <div>{{ count }}</div>
*/
export function useCountDown() {
// 定义函数参数和返回值类型
const count: Ref<number> = ref(0);
const timer: Ref<NodeJS.Timeout | null> = ref(null);
const countDown = (second: number, callback?: () => void) => {
if (count.value === 0 && timer.value === null) {
// 如果提供了回调函数,则调用它
if (callback) callback();
count.value = Number(second);
timer.value = setInterval(() => {
count.value--;
if (count.value === 0) {
clearInterval(timer.value!);
timer.value = null;
}
}, 1000);
}
};
onBeforeMount(() => {
// 确保 timer 有值再清除
timer.value && clearInterval(timer.value);
});
return {
count,
countDown,
};
}
<template>
<button :disabled="count !== 0" @click="countDown(3, logCountdown)">倒计时剩余 {{ `${count}秒` }} </button>
</template>
<script lang="ts" setup name="HomePage">
import { useCountDown } from '@/hooks';
// 倒计时
const { count, countDown } = useCountDown();
const logCountdown = () => {
console.log('触发倒计时回调函数');
};
</script>
防抖hooks
import { ref, Ref, onBeforeMount } from 'vue';
/**
* 防抖hooks
* @params {Function} fn 需要防抖的函数 delay 防抖时间
* @returns {Function} debounce 防抖函数
* @example
* const { debounce } = useDebounce()
* const fn = () => { console.log('防抖') }
* const debounceFn = debounce(fn, 1000)
* debounceFn()
*/
// 防抖函数的类型
interface DebounceFunction {
(fn: (...args: any[]) => void, delay: number): (...args: any[]) => void;
}
export function useDebounce(): { debounce: DebounceFunction } {
const debounce: DebounceFunction = (fn, delay) => {
let timer: ReturnType<typeof setTimeout> | null = null;
return function (this: any, ...args: any[]) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
return { debounce };
}
<template>
<button @click="debounceClick">防抖点击</button>
</template>
<script lang="ts" setup name="HomePage">
import { useDebounce } from '@/hooks';
// 防抖
const { debounce } = useDebounce();
const fn = () => {
console.log('取消点击一秒后打印');
};
const debounceClick = debounce(fn, 1000);
</script>
节流hooks
import { ref, Ref, onBeforeMount } from 'vue';
/**
* 节流hooks
* @params {Function} fn 需要节流的函数 delay 节流时间
* @returns {Function} throttle 节流函数
* @example
* const { throttle } = useThrottle()
* const fn = () => { console.log('节流') }
* const throttleFn = throttle(fn, 1000)
* throttleFn()
*/
// 节流函数的类型
interface ThrottleFunction {
(fn: (...args: any[]) => void, delay: number): (...args: any[]) => void;
}
export function useThrottle(): { throttle: ThrottleFunction } {
const throttle: ThrottleFunction = (fn, delay) => {
let timer: ReturnType<typeof setTimeout> | null = null;
return function (this: any, ...args: any[]) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
}
};
};
return { throttle };
}
<template>
<button @click="throttleClick">节流点击</button>
</template>
<script lang="ts" setup name="HomePage">
import { useThrottle } from '@/hooks';
const fn = () => {
console.log('一秒内只打印一次');
};
const { throttle } = useThrottle();
const throttleClick = throttle(fn, 1000);
</script>