创建自定义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