当前位置: 首页 > news >正文

VueUse:组合式API实用函数全集

VueUse 完全学习指南:组合式API实用函数集合

🎯 什么是 VueUse?

VueUse 是基于 组合式API(Composition API) 的实用函数集合,为Vue 3开发者提供了丰富的可复用逻辑功能。它通过提供大量预构建的组合函数,帮助开发者快速实现常见功能,提升开发效率。

🌟 核心特点

  • 基于组合式API:充分利用Vue 3的Composition API特性
  • 函数式编程:提供可复用、可组合的逻辑函数
  • 类型安全:完整的TypeScript支持
  • 轻量级:按需导入,减少打包体积
  • 生态丰富:涵盖传感器、动画、网络、状态管理等多个领域
  • 跨平台:支持Vue 3、Nuxt 3等多种环境

📦 安装与配置

NPM 安装

# 核心包
npm i @vueuse/core# 完整安装(包含所有插件)
npm i @vueuse/core @vueuse/components @vueuse/integrations

CDN 引入

<!-- 共享工具 -->
<script src="https://unpkg.com/@vueuse/shared"></script><!-- 核心功能 -->
<script src="https://unpkg.com/@vueuse/core"></script><script>// 作为 window.VueUse 全局可用const { useMouse, useLocalStorage } = window.VueUse
</script>

Nuxt 3 集成

自动安装模块
# 使用 nuxi 安装
npx nuxi@latest module add vueuse# 或使用 npm
npm i -D @vueuse/nuxt @vueuse/core
配置文件
// nuxt.config.ts
export default defineNuxtConfig({modules: ['@vueuse/nuxt',],
})
在Nuxt中使用
<script setup lang="ts">
// 无需导入,自动可用
const { x, y } = useMouse()
const isDark = usePreferredDark()
</script><template><div><p>鼠标位置: {{ x }}, {{ y }}</p><p>深色模式: {{ isDark ? '开启' : '关闭' }}</p></div>
</template>

🚀 基础使用

简单示例

<script setup>
import { useLocalStorage, useMouse, usePreferredDark } from '@vueuse/core'// 鼠标位置追踪
const { x, y } = useMouse()// 用户主题偏好
const isDark = usePreferredDark()// 本地存储状态持久化
const store = useLocalStorage('my-storage', {name: 'Apple',color: 'red',
})
</script><template><div><h2>鼠标位置</h2><p>x: {{ x }}, y: {{ y }}</p><h2>主题设置</h2><p>用户偏好深色模式: {{ isDark }}</p><h2>本地存储</h2><input v-model="store.name" placeholder="名称" /><input v-model="store.color" placeholder="颜色" /><p>存储内容: {{ store }}</p></div>
</template>

📚 核心功能分类

1. 🔍 传感器 (Sensors)

useMouse - 鼠标位置追踪
<script setup>
import { useMouse } from '@vueuse/core'const { x, y, sourceType } = useMouse()
</script><template><div><p>坐标: ({{ x }}, {{ y }})</p><p>输入类型: {{ sourceType }}</p></div>
</template>
useDeviceOrientation - 设备方向
<script setup>
import { useDeviceOrientation } from '@vueuse/core'const {isAbsolute,alpha,    // Z轴旋转 (0-360)beta,     // X轴旋转 (-180到180)gamma,    // Y轴旋转 (-90到90)
} = useDeviceOrientation()
</script><template><div><p>设备方向 - α: {{ alpha?.toFixed(1) }}°</p><p>设备方向 - β: {{ beta?.toFixed(1) }}°</p><p>设备方向 - γ: {{ gamma?.toFixed(1) }}°</p></div>
</template>
useGeolocation - 地理位置
<script setup>
import { useGeolocation } from '@vueuse/core'const { coords, locatedAt, error, resume, pause } = useGeolocation()
</script><template><div><div v-if="error">获取位置失败: {{ error.message }}</div><div v-else><p>纬度: {{ coords.latitude }}</p><p>经度: {{ coords.longitude }}</p><p>精度: {{ coords.accuracy }}米</p><p>定位时间: {{ locatedAt }}</p></div><button @click="resume">开始定位</button><button @click="pause">停止定位</button></div>
</template>

2. 🌐 浏览器 (Browser)

useLocalStorage - 本地存储
<script setup>
import { useLocalStorage } from '@vueuse/core'// 基础用法
const counter = useLocalStorage('counter', 0)// 对象存储
const user = useLocalStorage('user', {name: '张三',age: 25,preferences: {theme: 'dark',language: 'zh-CN'}
})// 自定义序列化
const settings = useLocalStorage('settings', new Set(), {serializer: {read: (v) => new Set(JSON.parse(v)),write: (v) => JSON.stringify(Array.from(v))}
})
</script><template><div><h3>计数器</h3><p>当前值: {{ counter }}</p><button @click="counter++">增加</button><button @click="counter--">减少</button><h3>用户信息</h3><input v-model="user.name" placeholder="姓名" /><input v-model.number="user.age" placeholder="年龄" /><select v-model="user.preferences.theme"><option value="light">浅色</option><option value="dark">深色</option></select></div>
</template>
useClipboard - 剪贴板操作
<script setup>
import { useClipboard } from '@vueuse/core'const { text, copy, copied, isSupported } = useClipboard()const input = ref('')const copyText = async () => {await copy(input.value)
}
</script><template><div><div v-if="!isSupported">浏览器不支持剪贴板API</div><div v-else><input v-model="input" placeholder="输入要复制的文本" /><button @click="copyText">复制</button><span v-if="copied" class="success">✓ 已复制</span><h4>剪贴板内容:</h4><p>{{ text || '无内容' }}</p></div></div>
</template><style scoped>
.success {color: green;margin-left: 8px;
}
</style>

3. 🎨 元素 (Elements)

useElementSize - 元素尺寸监听
<script setup>
import { useElementSize } from '@vueuse/core'const el = ref()
const { width, height } = useElementSize(el)
</script><template><div><div ref="el" class="resizable-box":style="{ resize: 'both', overflow: 'auto' }"><p>拖拽右下角调整大小</p><p>宽度: {{ Math.round(width) }}px</p><p>高度: {{ Math.round(height) }}px</p></div></div>
</template><style scoped>
.resizable-box {border: 2px solid #ccc;padding: 20px;min-width: 200px;min-height: 100px;background: #f9f9f9;
}
</style>
useIntersectionObserver - 交叉观察器
<script setup>
import { useIntersectionObserver } from '@vueuse/core'const target = ref()
const targetIsVisible = ref(false)const { stop } = useIntersectionObserver(target,([{ isIntersecting }]) => {targetIsVisible.value = isIntersecting},{threshold: 0.5  // 50%可见时触发}
)
</script><template><div><div style="height: 200vh"><p>向下滚动查看效果</p><div style="height: 50vh"></div><divref="target":class="{ visible: targetIsVisible }"class="target-element"><p>目标元素</p><p>可见状态: {{ targetIsVisible ? '可见' : '不可见' }}</p></div><div style="height: 100vh"></div></div></div>
</template><style scoped>
.target-element {padding: 20px;background: #f0f0f0;border: 2px solid #ddd;transition: all 0.3s ease;
}.target-element.visible {background: #e8f5e8;border-color: #4caf50;transform: scale(1.05);
}
</style>

4. ⏰ 时间 (Time)

useNow - 实时时间
<script setup>
import { useNow, useDateFormat } from '@vueuse/core'const now = useNow()
const formatted = useDateFormat(now, 'YYYY-MM-DD HH:mm:ss')// 自定义更新间隔
const nowWithInterval = useNow({ interval: 1000 })
</script><template><div><h3>实时时间</h3><p>当前时间: {{ formatted }}</p><p>时间戳: {{ now.getTime() }}</p><h3>秒级更新</h3><p>{{ useDateFormat(nowWithInterval, 'HH:mm:ss') }}</p></div>
</template>
useTimeAgo - 相对时间
<script setup>
import { useTimeAgo } from '@vueuse/core'const time1 = new Date(Date.now() - 30000) // 30秒前
const time2 = new Date(Date.now() - 300000) // 5分钟前
const time3 = new Date(Date.now() - 86400000) // 1天前const timeAgo1 = useTimeAgo(time1)
const timeAgo2 = useTimeAgo(time2)
const timeAgo3 = useTimeAgo(time3)
</script><template><div><h3>相对时间显示</h3><p>30秒前的时间: {{ timeAgo1 }}</p><p>5分钟前的时间: {{ timeAgo2 }}</p><p>1天前的时间: {{ timeAgo3 }}</p></div>
</template>

5. 🌐 网络 (Network)

useFetch - HTTP请求
<script setup>
import { useFetch } from '@vueuse/core'// 基础用法
const { data, error, isFetching } = useFetch('https://api.github.com/users/vuejs')// 带选项的用法
const {data: posts,error: postsError,isFetching: isLoadingPosts,execute: refetchPosts
} = useFetch('https://jsonplaceholder.typicode.com/posts', {refetch: false,  // 禁用自动请求
}).json()// POST 请求
const createPost = () => {return useFetch('https://jsonplaceholder.typicode.com/posts', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({title: '新文章',body: '文章内容',userId: 1,}),}).json()
}
</script><template><div><h3>GitHub用户信息</h3><div v-if="isFetching">加载中...</div><div v-else-if="error">错误: {{ error }}</div><div v-else-if="data"><img :src="data.avatar_url" width="50" /><p>用户名: {{ data.login }}</p><p>名称: {{ data.name }}</p></div><h3>文章列表</h3><button @click="refetchPosts" :disabled="isLoadingPosts">{{ isLoadingPosts ? '加载中...' : '获取文章' }}</button><div v-if="posts"><div v-for="post in posts.slice(0, 5)" :key="post.id" class="post"><h4>{{ post.title }}</h4><p>{{ post.body }}</p></div></div></div>
</template><style scoped>
.post {border: 1px solid #ddd;padding: 10px;margin: 10px 0;border-radius: 4px;
}
</style>

6. 🎯 状态管理 (State)

useToggle - 切换状态
<script setup>
import { useToggle } from '@vueuse/core'// 基础布尔切换
const [isVisible, toggle] = useToggle()// 带默认值的切换
const [theme, toggleTheme] = useToggle('light', 'dark')// 数组值切换
const [status, toggleStatus] = useToggle(['pending', 'success', 'error'])
</script><template><div><h3>基础切换</h3><button @click="toggle()">{{ isVisible ? '隐藏' : '显示' }}</button><p v-show="isVisible">这是一个可切换的内容</p><h3>主题切换</h3><button @click="toggleTheme()">当前主题: {{ theme }}</button><h3>状态循环</h3><button @click="toggleStatus()">当前状态: {{ status }}</button></div>
</template>
useCounter - 计数器
<script setup>
import { useCounter } from '@vueuse/core'const { count, inc, dec, set, reset } = useCounter(0, {min: 0,max: 10
})
</script><template><div><h3>计数器 (0-10)</h3><p>当前值: {{ count }}</p><div class="controls"><button @click="dec()" :disabled="count <= 0">-1</button><button @click="inc()" :disabled="count >= 10">+1</button><button @click="inc(5)">+5</button><button @click="set(5)">设为5</button><button @click="reset()">重置</button></div></div>
</template><style scoped>
.controls {display: flex;gap: 8px;margin-top: 10px;
}.controls button {padding: 4px 12px;
}
</style>

🎨 实际应用案例

案例1:响应式仪表板

<script setup>
import {useWindowSize,usePreferredDark,useLocalStorage,useElementSize,useNow,useDateFormat
} from '@vueuse/core'// 窗口尺寸
const { width: windowWidth, height: windowHeight } = useWindowSize()// 主题管理
const isDark = usePreferredDark()
const userTheme = useLocalStorage('user-theme', 'auto')// 组件尺寸
const dashboardRef = ref()
const { width: dashboardWidth, height: dashboardHeight } = useElementSize(dashboardRef)// 实时时间
const now = useNow()
const currentTime = useDateFormat(now, 'YYYY-MM-DD HH:mm:ss')// 用户设置
const settings = useLocalStorage('dashboard-settings', {showClock: true,showStats: true,refreshInterval: 5000,
})// 计算属性
const isCompact = computed(() => windowWidth.value < 768)
const themeClass = computed(() => {if (userTheme.value === 'auto') {return isDark.value ? 'dark' : 'light'}return userTheme.value
})
</script><template><div ref="dashboardRef":class="['dashboard', themeClass, { compact: isCompact }]"><!-- 头部信息 --><header class="dashboard-header"><h1>响应式仪表板</h1><div v-if="settings.showClock" class="clock">{{ currentTime }}</div></header><!-- 统计卡片 --><div v-if="settings.showStats" class="stats-grid"><div class="stat-card"><h3>窗口尺寸</h3><p>{{ windowWidth }} × {{ windowHeight }}</p></div><div class="stat-card"><h3>仪表板尺寸</h3><p>{{ Math.round(dashboardWidth) }} × {{ Math.round(dashboardHeight) }}</p></div><div class="stat-card"><h3>设备类型</h3><p>{{ isCompact ? '移动设备' : '桌面设备' }}</p></div><div class="stat-card"><h3>主题偏好</h3><p>{{ isDark ? '深色模式' : '浅色模式' }}</p></div></div><!-- 设置面板 --><div class="settings-panel"><h3>设置</h3><label><input v-model="settings.showClock" type="checkbox" />显示时钟</label><label><input v-model="settings.showStats" type="checkbox" />显示统计</label><label>主题选择:<select v-model="userTheme"><option value="auto">自动</option><option value="light">浅色</option><option value="dark">深色</option></select></label></div></div>
</template><style scoped>
.dashboard {padding: 20px;min-height: 100vh;transition: all 0.3s ease;
}.dashboard.light {background: #f5f5f5;color: #333;
}.dashboard.dark {background: #1a1a1a;color: #fff;
}.dashboard-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 20px;padding-bottom: 10px;border-bottom: 1px solid currentColor;
}.clock {font-family: monospace;font-size: 1.2em;
}.stats-grid {display: grid;grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));gap: 16px;margin-bottom: 20px;
}.dashboard.compact .stats-grid {grid-template-columns: 1fr;
}.stat-card {padding: 16px;border-radius: 8px;background: rgba(255, 255, 255, 0.1);border: 1px solid rgba(255, 255, 255, 0.2);
}.dashboard.light .stat-card {background: rgba(0, 0, 0, 0.05);border-color: rgba(0, 0, 0, 0.1);
}.settings-panel {padding: 20px;border-radius: 8px;background: rgba(255, 255, 255, 0.1);
}.settings-panel label {display: block;margin: 10px 0;
}.settings-panel select {margin-left: 10px;padding: 4px;
}
</style>

案例2:图片懒加载组件

<script setup>
import { useIntersectionObserver, useImage } from '@vueuse/core'const props = defineProps({src: String,alt: String,placeholder: String,threshold: {type: Number,default: 0.1}
})const target = ref()
const targetIsVisible = ref(false)
const shouldLoad = ref(false)// 交叉观察器
const { stop } = useIntersectionObserver(target,([{ isIntersecting }]) => {targetIsVisible.value = isIntersectingif (isIntersecting && !shouldLoad.value) {shouldLoad.value = truestop() // 停止观察,避免重复加载}},{threshold: props.threshold}
)// 图片加载状态
const { isLoading, error } = useImage({src: computed(() => shouldLoad.value ? props.src : ''),loading: 'lazy'
})const currentSrc = computed(() => {if (error.value) return props.placeholderif (!shouldLoad.value) return props.placeholderif (isLoading.value) return props.placeholderreturn props.src
})
</script><template><div ref="target" class="lazy-image-container":class="{loading: isLoading,error: error,visible: targetIsVisible}"><img :src="currentSrc" :alt="alt"class="lazy-image"@load="$emit('loaded')"@error="$emit('error')"/><div v-if="isLoading" class="loading-indicator"><div class="spinner"></div></div><div v-if="error" class="error-indicator">❌ 加载失败</div></div>
</template><style scoped>
.lazy-image-container {position: relative;display: inline-block;background: #f0f0f0;border-radius: 4px;overflow: hidden;
}.lazy-image {width: 100%;height: auto;transition: opacity 0.3s ease;
}.loading-indicator,
.error-indicator {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);
}.spinner {width: 20px;height: 20px;border: 2px solid #ddd;border-top: 2px solid #666;border-radius: 50%;animation: spin 1s linear infinite;
}@keyframes spin {to { transform: rotate(360deg); }
}.lazy-image-container.loading .lazy-image {opacity: 0.3;
}.lazy-image-container.error .lazy-image {opacity: 0.5;filter: grayscale(100%);
}
</style>

案例3:全局状态管理

<!-- composables/useGlobalState.js -->
<script>
import { createGlobalState, useStorage } from '@vueuse/core'// 创建全局状态
export const useGlobalState = createGlobalState(() => {// 用户信息const user = useStorage('user', {id: null,name: '',avatar: '',isLoggedIn: false})// 应用设置const appSettings = useStorage('app-settings', {theme: 'auto',language: 'zh-CN',notifications: true})// 购物车const cart = useStorage('shopping-cart', [])// 方法const login = (userData) => {user.value = {...userData,isLoggedIn: true}}const logout = () => {user.value = {id: null,name: '',avatar: '',isLoggedIn: false}}const addToCart = (item) => {const existingItem = cart.value.find(cartItem => cartItem.id === item.id)if (existingItem) {existingItem.quantity += 1} else {cart.value.push({ ...item, quantity: 1 })}}const removeFromCart = (itemId) => {const index = cart.value.findIndex(item => item.id === itemId)if (index > -1) {cart.value.splice(index, 1)}}const updateTheme = (theme) => {appSettings.value.theme = theme}// 计算属性const cartTotal = computed(() => {return cart.value.reduce((total, item) => total + item.price * item.quantity, 0)})const cartItemCount = computed(() => {return cart.value.reduce((count, item) => count + item.quantity, 0)})return {// 状态user: readonly(user),appSettings: readonly(appSettings),cart: readonly(cart),// 方法login,logout,addToCart,removeFromCart,updateTheme,// 计算属性cartTotal,cartItemCount}
})
</script><!-- 使用示例 -->
<script setup>
import { useGlobalState } from './composables/useGlobalState'const {user,cart,cartTotal,cartItemCount,addToCart,removeFromCart,login,logout
} = useGlobalState()const sampleProducts = [{ id: 1, name: 'iPhone 15', price: 5999 },{ id: 2, name: 'MacBook Pro', price: 12999 },{ id: 3, name: 'AirPods', price: 1299 }
]
</script><template><div class="app"><!-- 头部 --><header class="header"><h1>电商应用</h1><div class="user-section"><div v-if="user.isLoggedIn" class="user-info"><span>欢迎,{{ user.name }}</span><button @click="logout">登出</button></div><button v-else @click="login({ id: 1, name: '张三', avatar: '' })">登录</button><div class="cart-info">🛒 {{ cartItemCount }} 项商品<span v-if="cartItemCount > 0">- ¥{{ cartTotal.toFixed(2) }}</span></div></div></header><!-- 商品列表 --><main class="main"><h2>商品列表</h2><div class="products"><div v-for="product in sampleProducts" :key="product.id" class="product-card"><h3>{{ product.name }}</h3><p>¥{{ product.price }}</p><button @click="addToCart(product)">加入购物车</button></div></div><!-- 购物车 --><div v-if="cart.length > 0" class="cart"><h2>购物车</h2><div v-for="item in cart" :key="item.id" class="cart-item"><span>{{ item.name }}</span><span>数量: {{ item.quantity }}</span><span>¥{{ (item.price * item.quantity).toFixed(2) }}</span><button @click="removeFromCart(item.id)">删除</button></div><div class="cart-total">总计: ¥{{ cartTotal.toFixed(2) }}</div></div></main></div>
</template><style scoped>
.app {max-width: 1200px;margin: 0 auto;padding: 20px;
}.header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 20px;padding-bottom: 10px;border-bottom: 1px solid #ddd;
}.user-section {display: flex;align-items: center;gap: 20px;
}.products {display: grid;grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));gap: 16px;margin-bottom: 40px;
}.product-card {border: 1px solid #ddd;padding: 16px;border-radius: 8px;text-align: center;
}.cart {border-top: 1px solid #ddd;padding-top: 20px;
}.cart-item {display: flex;justify-content: space-between;align-items: center;padding: 8px 0;border-bottom: 1px solid #eee;
}.cart-total {font-size: 1.2em;font-weight: bold;text-align: right;margin-top: 10px;
}
</style>

🛠️ 最佳实践

1. 性能优化

<script setup>
import { useDebounceFn, useThrottleFn } from '@vueuse/core'// 防抖搜索
const searchQuery = ref('')
const searchResults = ref([])const debouncedSearch = useDebounceFn(async (query) => {if (query.length < 2) {searchResults.value = []return}try {const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`)searchResults.value = await response.json()} catch (error) {console.error('搜索失败:', error)}
}, 300)watch(searchQuery, debouncedSearch)// 节流滚动事件
const scrollY = ref(0)const throttledScrollHandler = useThrottleFn(() => {scrollY.value = window.scrollY
}, 100)onMounted(() => {window.addEventListener('scroll', throttledScrollHandler)
})onUnmounted(() => {window.removeEventListener('scroll', throttledScrollHandler)
})
</script>

2. 组合函数封装

// composables/useApi.js
import { useFetch } from '@vueuse/core'export function useApi(endpoint, options = {}) {const baseURL = 'https://api.example.com'const {data,error,isFetching,execute,...rest} = useFetch(`${baseURL}${endpoint}`, {beforeFetch({ url, options }) {// 添加认证头const token = localStorage.getItem('auth-token')if (token) {options.headers = {...options.headers,Authorization: `Bearer ${token}`}}return { url, options }},afterFetch(ctx) {// 处理响应数据if (ctx.data && ctx.data.success === false) {throw new Error(ctx.data.message || '请求失败')}return ctx},onFetchError(ctx) {// 错误处理console.error('API请求错误:', ctx.error)return ctx},...options}).json()return {data,error,loading: isFetching,refetch: execute,...rest}
}// 使用示例
export function useUserList() {return useApi('/users')
}export function useUserDetail(userId) {return useApi(computed(() => `/users/${userId.value}`), {refetch: false})
}

3. 错误处理

<script setup>
import { useErrorHandler } from '@vueuse/core'// 全局错误处理
const { onError } = useErrorHandler()onError((error, instance, info) => {console.error('Vue错误:', error)console.error('组件实例:', instance)console.error('错误信息:', info)// 发送错误报告reportError({message: error.message,stack: error.stack,component: instance?.$options.name,info})
})// API错误处理
const { data, error } = useFetch('/api/data', {onFetchError(ctx) {// 统一错误处理const errorMessage = ctx.data?.message || '网络请求失败'ElMessage.error(errorMessage)// 根据错误码处理if (ctx.response?.status === 401) {// 未授权,跳转登录router.push('/login')}return ctx}
})function reportError(errorInfo) {// 发送到错误监控服务fetch('/api/errors', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(errorInfo)}).catch(console.error)
}
</script>

🎯 总结

VueUse 是Vue 3生态系统中不可或缺的工具库,它提供了:

丰富的功能:涵盖传感器、浏览器、网络、状态管理等各个方面
开箱即用:无需复杂配置,直接导入使用
类型安全:完整的TypeScript支持,提供良好的开发体验
性能优秀:按需导入,优化包体积
生态完善:与Nuxt、Vue Router等完美集成
持续更新:活跃的社区维护,功能不断丰富

💡 学习建议

  1. 从基础开始:先掌握常用的状态管理和浏览器相关函数
  2. 结合实际项目:在真实项目中实践,加深理解
  3. 阅读源码:学习优秀的组合式API设计模式
  4. 创建自定义组合函数:根据项目需求封装可复用逻辑
  5. 关注生态发展:跟进新功能和最佳实践

📚 推荐学习路径

第一阶段:基础入门
├── useLocalStorage, useSessionStorage (状态持久化)
├── useMouse, useWindowSize (传感器)
├── useToggle, useCounter (状态管理)
└── useFetch (网络请求)第二阶段:进阶应用
├── useIntersectionObserver (性能优化)
├── useDebounceFn, useThrottleFn (性能优化)
├── useClipboard, usePermission (浏览器API)
└── createGlobalState (全局状态)第三阶段:高级应用
├── 自定义组合函数设计
├── 插件开发和集成
├── 性能优化实践
└── 大型项目架构设计

通过系统学习和实践VueUse,您可以大大提高Vue 3开发效率,写出更加优雅和可维护的代码。


开始您的VueUse学习之旅吧! 🚀

💡 开发建议:建议从项目实际需求出发,逐步引入VueUse函数,避免过度使用。重点关注代码的可读性和可维护性。

http://www.xdnf.cn/news/791011.html

相关文章:

  • ADI硬件笔试面试题型解析上
  • DevEco Studio的使用
  • VUE组件库开发 八股
  • 时态--10--被动语态
  • Selenium 中 JavaScript 点击操作的原理及应用
  • Java:跨越时代的编程语言,持续引领技术革新
  • IPython 使用技巧整理
  • 强化学习鱼书(10)——更多深度强化学习的算法
  • Spring AI 项目实战(一):Spring AI 核心模块入门
  • 【Linux】Linux 进程基础
  • 华为港城 RAG 推理训练新突破:过程监督助力 5k 样本性能超越 90k 模型
  • 神经符号集成-三篇综述
  • COMSOL多边形骨料堆积混凝土水化热传热模拟
  • shell脚本总结13:head -c 和cut -c的区别
  • C++ 中的依赖注入(Dependency Injection)
  • Lua和JS的继承原理
  • 【PhysUnits】15.12 去Typenum库的SI 单位制词头实现(prefix.rs)
  • pycharm如何查看git历史版本变更信息
  • AI地面垃圾检测算法智能分析网关V4打造城市/公园/校园等场景环保卫生监管解决方案
  • MySQL 日志数据同步的详细教程
  • Message=“HalconDotNet.HHandleBase”的类型初始值设定项引发异常
  • JS手写代码篇---手写call函数
  • ADC接口电路设计详解
  • 动态规划-647.回文子串-力扣(LeetCode)
  • Double/Debiased Machine Learning
  • 同余的概念和基本性质
  • cursor对话
  • DPDK与网络协议栈
  • 从 Docker 到 Containerd:Kubernetes 容器运行时迁移实战指南
  • AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年6月3日第97弹