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>

猜你喜欢

转载自blog.csdn.net/weixin_43743175/article/details/134731033