引言
在Vue 3的生态系统中,组合式API(Composition API)为我们带来了更灵活的代码组织方式。而VueUse作为Vue生态中最受欢迎的工具库之一,为开发者提供了200多个实用的组合式函数,极大地简化了日常开发工作。本期我们将深入探索VueUse这个强大的工具库。
库介绍
基本信息
- 库名称:VueUse
- GitHub Stars:19.5k+ ⭐
- 维护状态:活跃维护,定期更新
- 兼容性:Vue 2.7+ / Vue 3.0+
- 包大小:Tree-shakable,按需引入
- 依赖关系:基于Vue响应式系统
核心特点
VueUse是一个基于Vue组合式API的实用工具库,它将常见的开发需求封装成可复用的组合式函数。主要特点包括:
- 丰富的功能集合:提供200+个实用函数,涵盖状态管理、浏览器API、动画、网络请求等各个方面
- 类型安全:完整的TypeScript支持,提供优秀的开发体验
- Tree-shakable:支持按需引入,不会增加不必要的包体积
- SSR友好:完美支持服务端渲染
- 灵活可配置:大部分函数都提供丰富的配置选项
- 响应式设计:充分利用Vue的响应式系统
安装使用
安装命令
bash
# 使用 pnpm(推荐)
pnpm add @vueuse/core
# 安装额外的集成包
pnpm add @vueuse/components @vueuse/integrations
基础使用示例
vue
<template>
<div>
<p>鼠标位置: {{ x }}, {{ y }}</p>
<p>窗口大小: {{ width }} x {{ height }}</p>
<button @click="toggle">
{{ isOnline ? '在线' : '离线' }}
</button>
</div>
</template>
<script setup>
import { useMouse, useWindowSize, useOnline } from '@vueuse/core'
// 获取鼠标位置
const { x, y } = useMouse()
// 获取窗口大小
const { width, height } = useWindowSize()
// 检测网络状态
const { isOnline, toggle } = useOnline()
</script>
VueUse API分类详解
1. 状态管理类
useLocalStorage / useSessionStorage
javascript
// 响应式的本地存储
const name = useLocalStorage('user-name', '默认值')
const settings = useSessionStorage('app-settings', { theme: 'light' })
useToggle
javascript
// 布尔值切换
const [isVisible, toggle] = useToggle()
const [status, toggleStatus] = useToggle('active', 'inactive')
useCounter
javascript
// 计数器管理
const { count, inc, dec, set, reset } = useCounter(0, { min: 0, max: 100 })
2. 浏览器API类
useMouse / useMousePressed
javascript
// 鼠标位置和状态
const { x, y } = useMouse()
const { pressed } = useMousePressed()
useKeyboard / useKeyModifier
javascript
// 键盘事件
const { ctrl, shift, alt, meta } = useKeyModifier()
const keys = useKeyboard()
useClipboard
javascript
// 剪贴板操作
const { text, copy, copied, isSupported } = useClipboard()
useFullscreen
javascript
// 全屏控制
const { isFullscreen, enter, exit, toggle } = useFullscreen()
3. 传感器类
useDeviceOrientation
javascript
// 设备方向
const { alpha, beta, gamma, absolute } = useDeviceOrientation()
useGeolocation
javascript
// 地理位置
const { coords, locatedAt, error } = useGeolocation()
useBattery
javascript
// 电池状态
const { charging, level, dischargingTime } = useBattery()
4. 网络类
useFetch
javascript
// HTTP请求
const { data, error, isFetching } = useFetch('/api/users')
useWebSocket
javascript
// WebSocket连接
const { status, data, send, open, close } = useWebSocket('ws://localhost:8080')
5. 动画类
useTransition
javascript
// 数值过渡动画
const source = ref(0)
const output = useTransition(source, {
duration: 1000,
transition: TransitionPresets.easeInOutCubic
})
useInterval / useTimeout
javascript
// 定时器管理
const { pause, resume, isActive } = useInterval(() => {
console.log('每秒执行')
}, 1000)
6. 元素操作类
useElementSize
javascript
// 元素尺寸监听
const el = ref()
const { width, height } = useElementSize(el)
useIntersectionObserver
javascript
// 元素可见性检测
const target = ref()
const { isIntersecting } = useIntersectionObserver(target)
useResizeObserver
javascript
// 元素大小变化监听
const el = ref()
useResizeObserver(el, (entries) => {
console.log('元素大小改变')
})
7. 实用工具类
useDebounce / useThrottle
javascript
// 防抖和节流
const input = ref('')
const debouncedValue = useDebounce(input, 500)
const throttledValue = useThrottle(input, 1000)
useAsyncState
javascript
// 异步状态管理
const { state, isReady, isLoading, error, execute } = useAsyncState(
() => fetchUserData(),
null
)
useVModel
javascript
// 双向绑定辅助
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
const data = useVModel(props, 'modelValue', emit)
实际应用场景
1. 响应式布局系统
vue
<template>
<div class="responsive-layout">
<aside v-if="!isMobile" class="sidebar">
侧边栏内容
</aside>
<main :class="{ 'full-width': isMobile }">
<header>
<button @click="toggleTheme">
{{ isDark ? '🌙' : '☀️' }}
</button>
</header>
<div class="content">
主要内容区域
</div>
</main>
</div>
</template>
<script setup>
import { useBreakpoints, useDark, useToggle } from '@vueuse/core'
// 响应式断点
const breakpoints = useBreakpoints({
mobile: 768,
tablet: 1024,
desktop: 1280
})
const isMobile = breakpoints.smaller('tablet')
// 暗黑模式
const isDark = useDark()
const toggleTheme = useToggle(isDark)
</script>
2. 实时数据监控面板
vue
<template>
<div class="dashboard">
<div class="status-bar">
<span :class="{ online: isOnline, offline: !isOnline }">
{{ isOnline ? '在线' : '离线' }}
</span>
<span>电池: {{ batteryLevel }}%</span>
<span>{{ formattedTime }}</span>
</div>
<div class="charts">
<canvas ref="chartCanvas"></canvas>
</div>
<div class="controls">
<button @click="startMonitoring" :disabled="isMonitoring">
开始监控
</button>
<button @click="stopMonitoring" :disabled="!isMonitoring">
停止监控
</button>
</div>
</div>
</template>
<script setup>
import {
useOnline,
useBattery,
useNow,
useInterval,
useElementSize
} from '@vueuse/core'
// 网络状态
const isOnline = useOnline()
// 电池状态
const { level: batteryLevel } = useBattery()
// 实时时间
const now = useNow()
const formattedTime = computed(() =>
now.value.toLocaleTimeString()
)
// 图表容器
const chartCanvas = ref()
const { width, height } = useElementSize(chartCanvas)
// 监控控制
const isMonitoring = ref(false)
const { pause, resume } = useInterval(() => {
// 更新图表数据
updateChartData()
}, 1000, { immediate: false })
const startMonitoring = () => {
isMonitoring.value = true
resume()
}
const stopMonitoring = () => {
isMonitoring.value = false
pause()
}
</script>
3. 高级表单处理
vue
<template>
<form @submit.prevent="handleSubmit">
<div class="form-group">
<input
v-model="form.email"
type="email"
placeholder="邮箱"
:class="{ error: emailError }"
>
<span v-if="emailError" class="error-text">
{{ emailError }}
</span>
</div>
<div class="form-group">
<input
v-model="form.password"
type="password"
placeholder="密码"
>
</div>
<button
type="submit"
:disabled="!isFormValid || isSubmitting"
>
{{ isSubmitting ? '提交中...' : '登录' }}
</button>
<div v-if="submitError" class="error">
{{ submitError }}
</div>
</form>
</template>
<script setup>
import {
useVModel,
useAsyncValidator,
useAsyncState,
useDebounce
} from '@vueuse/core'
// 表单数据
const form = reactive({
email: '',
password: ''
})
// 邮箱验证(防抖)
const debouncedEmail = useDebounce(() => form.email, 500)
const { pass: isEmailValid, errorMessage: emailError } = useAsyncValidator(
debouncedEmail,
async (value) => {
if (!value) return '邮箱不能为空'
if (!/\S+@\S+\.\S+/.test(value)) return '邮箱格式不正确'
// 异步验证邮箱是否已注册
const exists = await checkEmailExists(value)
if (!exists) return '邮箱未注册'
return true
}
)
// 表单验证
const isFormValid = computed(() =>
isEmailValid.value && form.password.length >= 6
)
// 提交处理
const {
state: submitResult,
isLoading: isSubmitting,
error: submitError,
execute: submitForm
} = useAsyncState(
() => loginUser(form),
null,
{ immediate: false }
)
const handleSubmit = () => {
if (isFormValid.value) {
submitForm()
}
}
</script>
优缺点分析
优势
- 开发效率高:提供大量开箱即用的功能,减少重复代码编写
- 类型安全:完整的TypeScript支持,减少运行时错误
- 性能优秀:基于Vue响应式系统,性能表现良好
- 文档完善:官方文档详细,示例丰富
- 社区活跃:持续更新,bug修复及时
- 灵活性强:大部分函数都支持自定义配置
局限性
- 学习成本:函数众多,需要时间熟悉各个API
- 包体积:虽然支持tree-shaking,但完整引入会增加包体积
- Vue绑定:仅适用于Vue项目,不能在其他框架中使用
- 版本依赖:需要Vue 2.7+或Vue 3.0+
最佳实践建议
1. 按需引入
javascript
// 推荐:按需引入
import { useMouse, useLocalStorage } from '@vueuse/core'
// 避免:全量引入
import * as VueUse from '@vueuse/core'
2. 合理使用响应式
javascript
// 合理利用响应式特性
const { x, y } = useMouse()
const position = computed(() => `${x.value}, ${y.value}`)
// 避免不必要的响应式转换
const staticConfig = { timeout: 5000 } // 静态配置无需响应式
3. 错误处理
javascript
const { data, error, isFinished } = useFetch('/api/data')
watchEffect(() => {
if (error.value) {
console.error('请求失败:', error.value)
// 处理错误逻辑
}
})
总结
VueUse是Vue生态系统中不可或缺的工具库,它通过提供丰富的组合式函数,极大地提升了Vue开发的效率和体验。无论是处理浏览器API、状态管理,还是实现复杂的交互效果,VueUse都能提供优雅的解决方案。
推荐使用场景:
- Vue 3项目的快速开发
- 需要大量浏览器API交互的应用
- 追求代码复用性和可维护性的项目
- 需要响应式状态管理的复杂应用
VueUse不仅是一个工具库,更是学习Vue组合式API最佳实践的优秀范例。通过研究其源码和使用方式,能够帮助开发者更好地理解和运用Vue 3的核心特性。