VueUse 是 Vue 生态系统中目前最流行、功能最强大的工具函数集合(Utility Functions Collection)。它基于 Composition API 设计,提供了超过 200+ 个开箱即用的函数,涵盖了从基础状态管理、浏览器 API 调用、DOM 操作到高级动画、网络请求等几乎所有前端开发场景。
它的核心理念是: "将原本非响应式的浏览器 API 或复杂逻辑,封装成响应式的组合式函数(Composables),让开发者无需重复造轮子。"
一、核心优势与特点
- 开箱即用 (Out of the Box):无需配置,安装即可使用,覆盖了绝大多数日常开发需求。
- 纯 Composition API :所有函数均以
use开头(如useMouse,useStorage),完美契合 Vue 3 的逻辑复用模式。 - 自动清理副作用:内部自动处理事件监听移除、定时器清除等,防止内存泄漏。
- TypeScript 友好:提供完整的类型定义,开发体验极佳。
- SSR 支持:大多数函数都兼容服务端渲染(Nuxt.js 等)。
- 按需引入:支持模块化导入,不会显著增加打包体积。
二、主要功能分类及使用场景
VueUse 的功能非常庞大,以下是几类最常用的场景:
1. 状态管理与持久化
- 场景:需要在本地存储用户偏好、表单草稿或登录态。
- 函数 :
useStorage,useLocalStorage,useSessionStorage,useMemory. - 优势:自动同步响应式数据与浏览器存储,刷新页面数据不丢失。
2. 浏览器信息与设备感知
- 场景:获取网络状态、电池电量、地理位置、屏幕方向、深色模式检测。
- 函数 :
useNetwork,useBattery,useGeolocation,useDark,useToggle. - 优势:将异步或事件驱动的 API 转化为响应式引用(Ref)。
3. DOM 操作与交互
- 场景:监听鼠标位置、元素尺寸变化、全屏控制、点击外部关闭弹窗。
- 函数 :
useMouse,useElementSize,useFullscreen,onClickOutside,useDraggable. - 优势:省去手动添加/移除事件监听器的繁琐代码。
4. 动画与过渡
- 场景:数字计数动画、列表过渡、鼠标跟随效果。
- 函数 :
useTransition,useRafFn,useSpring(需配合 @vueuse/motion). - 优势:轻松实现流畅的数值变化和交互动画。
5. 工具与格式化
- 场景:防抖节流、日期格式化、Base64 编码、剪贴板操作。
- 函数 :
useDebounceFn,useThrottleFn,useDateFormat,useClipboard,useBase64.
三、完整使用示例
1. 安装
bash
# npm
npm install @vueuse/core
# yarn
yarn add @vueuse/core
# pnpm
pnpm add @vueuse/core
提示 :如果你使用的是 Nuxt 3,它已内置 VueUse,只需在 nuxt.config.ts 中配置即可,无需单独安装。
2. 基础示例:深色模式切换 + 本地存储
这个示例展示了如何使用 useDark 和 useToggle 快速实现主题切换,并自动保存到本地。
vue
<script setup>
import { useDark, useToggle } from '@vueuse/core'
// 1. 监听系统深色模式,并同步到 class="dark"
const isDark = useDark({
selector: 'html', // 默认就是 html,可省略
valueDark: 'dark',
valueLight: '',
})
// 2. 创建一个切换函数
const toggleDark = useToggle(isDark)
</script>
<template>
<div class="app-container">
<h1>当前模式:{{ isDark ? '🌙 深色' : '☀️ 浅色' }}</h1>
<button @click="toggleDark()">
切换主题
</button>
</div>
</template>
<style>
/* 假设你的 CSS 变量已配置好 */
html.dark {
background-color: #121212;
color: #fff;
}
</style>
3. 进阶示例:综合仪表盘(鼠标追踪 + 网络状态 + 剪贴板)
这个示例模拟一个后台仪表盘的小部件,展示多个功能的组合使用。
vue
<script setup>
import {
useMouse,
useNetwork,
useClipboard,
useDateFormat,
useNow,
useFullscreen
} from '@vueuse/core'
import { ref } from 'vue'
// --- 1. 鼠标追踪 ---
const { x, y } = useMouse()
// --- 2. 网络状态监控 ---
const network = useNetwork()
const networkStatus = computed(() => {
if (!network.isOnline.value) return '❌ 离线'
return `✅ 在线 (${network.downlink || '?'}Mbps)`
})
// --- 3. 剪贴板操作 ---
const inputText = ref('https://vueuse.org')
const { copy, copied, text } = useClipboard({ source: inputText })
// --- 4. 时间格式化 ---
const now = useNow()
const formattedTime = computed(() => useDateFormat(now, 'YYYY-MM-DD HH:mm:ss').value)
// --- 5. 全屏控制 ---
const { isFullscreen, toggle } = useFullscreen()
</script>
<template>
<div class="dashboard p-4 border rounded shadow-lg max-w-md mx-auto mt-10">
<h2 class="text-xl font-bold mb-4">VueUse 综合演示</h2>
<!-- 鼠标位置 -->
<div class="mb-3">
<p class="text-sm text-gray-500">鼠标位置:</p>
<p>X: {{ x }}, Y: {{ y }}</p>
</div>
<!-- 网络状态 -->
<div class="mb-3">
<p class="text-sm text-gray-500">网络状态:</p>
<p :class="network.isOnline ? 'text-green-600' : 'text-red-600'">
{{ networkStatus }}
</p>
</div>
<!-- 时间显示 -->
<div class="mb-3">
<p class="text-sm text-gray-500">当前服务器时间:</p>
<p class="font-mono">{{ formattedTime }}</p>
</div>
<!-- 剪贴板功能 -->
<div class="mb-3">
<p class="text-sm text-gray-500 mb-1">复制链接:</p>
<div class="flex gap-2">
<input v-model="inputText" class="border px-2 py-1 rounded flex-1" />
<button
@click="copy()"
class="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600"
>
{{ copied ? '已复制!' : '复制' }}
</button>
</div>
</div>
<!-- 全屏功能 -->
<div class="mb-3">
<button
@click="toggle"
class="w-full bg-gray-800 text-white py-2 rounded"
>
{{ isFullscreen ? '退出全屏' : '进入全屏' }}
</button>
</div>
</div>
</template>
4. 高级场景:防抖搜索请求
在实际开发中,搜索框输入通常需要做防抖处理。
vue
<script setup>
import { ref } from 'vue'
import { useDebounceFn } from '@vueuse/core'
const searchText = ref('')
const results = ref([])
const loading = ref(false)
// 定义搜索逻辑
const searchAPI = async (query) => {
if (!query) {
results.value = []
return
}
loading.value = true
// 模拟 API 请求
await new Promise(resolve => setTimeout(resolve, 500))
results.value = [`结果 1: ${query}`, `结果 2: ${query}`, `结果 3: ${query}`]
loading.value = false
}
// 使用 useDebounceFn 创建防抖函数 (延迟 500ms)
const debouncedSearch = useDebounceFn((query) => {
searchAPI(query)
}, 500)
// 监听输入变化
const handleInput = () => {
debouncedSearch(searchText.value)
}
</script>
<template>
<div>
<input
v-model="searchText"
@input="handleInput"
placeholder="输入内容搜索(防抖 500ms)..."
class="border p-2 w-full"
/>
<div v-if="loading">加载中...</div>
<ul>
<li v-for="item in results" :key="item">{{ item }}</li>
</ul>
</div>
</template>
四、最佳实践建议
- 按需导入 :虽然 VueUse 支持全局自动导入(通过 unplugin-vue-components),但在大型项目中,显式导入(如
import { useMouse } from '@vueuse/core')更有利于树摇(Tree-shaking)和代码清晰度。 - 不要过度封装 :如果逻辑非常简单(例如只是简单的
ref),不必强行使用 VueUse,保持代码简洁。 - 阅读文档:VueUse 的文档非常详细,每个函数都有 "Source", "Types", "Demo" 链接,遇到问题优先查阅官方文档。
- 组合使用 :VueUse 的强大在于组合。你可以将
useMouse和useElementBounding结合,轻松实现复杂的鼠标交互效果。
五、总结
VueUse 是 Vue 3 开发的瑞士军刀。它极大地减少了样板代码,让开发者能专注于业务逻辑本身。无论是简单的"复制文本"、"深色模式",还是复杂的"手势识别"、"虚拟列表",VueUse 都能提供成熟、稳定且高性能的解决方案。对于任何 Vue 3 项目,它都是首选的依赖库之一。
官方文档地址:https://vueuse.org/ (支持中文)