官方文档: vueuse.org/
中文文档: www.vueusejs.com/
一、介绍
Vueuse
是一个基于 Vue3 的功能强大的 Vue.js 生态系统工具库,它提供了一系列的可重用的Vue组件
和Composition API
(组合式API)函数,旨在帮助开发者更高效地构建 Vue 应用。这个库利用 Vue 3 的响应式系统,提供了一系列可复用的功能函数(也称为“钩子”或“hooks”),这些函数覆盖了从基础的状态管理到集成浏览器API的高级用途。
Vueuse
具有以下主要特点,使其成为 Vue.js 开发中的有力助手:
-
丰富的钩子函数:VueUse 提供了大量的钩子函数,覆盖了诸如访问浏览器位置、使用本地存储、监听事件、实现响应式状态等常见需求。
-
基于 Composition API:所有的钩子函数都是基于 Vue 3 的 Composition API 设计的,这意味着它们可以在 Vue 组件的
setup
函数中直接使用,使得代码更加模块化和可复用。 -
TypeScript 支持:Vueuse 对 TypeScript 提供了良好的支持,所有的组件和函数都有完整的类型定义,提供了更好的代码提示和类型安全性。
-
可按需引入(轻量级和模块化) :Vueuse 由一系列独立的模块组成,每个模块都提供一个特定的功能或功能集,你可以只引入需要的钩子函数,而不必引入整个库,这有助于减小最终打包文件的大小。
二、使用
安装
下载包的方式:
npm i @vueuse/core
CDN 引入方式:
<script src="https://unpkg.com/@vueuse/shared"></script>
<script src="https://unpkg.com/@vueuse/core"></script>
使用方法
VueUse
中的大多数函数都返回一个refs
对象,你可以使用ES6
的对象解构语法来获取。
<script setup>
import { useLocalStorage, useMouse } from '@vueuse/core'
// 跟踪鼠标位置
const { x, y } = useMouse()
console.log(x.value)
// 将状态保存在 localStorage 中
const store = useLocalStorage(
'my-storage',
{
name: 'Apple',
color: 'red',
},
)
</script>
三、常用函数
templateRef(将 ref 绑定到模板元素)
<template>
<div ref="target"></div>
</template>
<script lang="ts">
import { templateRef } from '@vueuse/core'
export default {
setup() {
const target = templateRef('target')
// 无需返回 target,它会自动绑定到模板元素上
}
}
</script>
在 <script setup>
中,所有变量都将暴露在模板中,你可以使用 ref
代替 templateRef
,因为它们的功能是相同的。
<script setup lang="ts">
import { ref } from 'vue'
const target = ref<HTMLElement | null>(null)
</script>
useVModel(v-mode)
v-model
简写,props + emit -> ref
父组件:
<MyCheckbox v-model:checkedVal="isChecked"></MyCheckbox>
<script setup>
const isChecked = ref(true)
</script>
MyCheckbox.vue:
<script setup>
import { useVModel } from '@vueuse/core'
const props = defineProps({
checkedVal: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:checkedVal'])
const checked = useVModel(props, 'checkedVal', emit)
const changeChecked = () => {
checked.value = !checked.value
}
</script>
useToggle(切换布尔值状态)
<template>
<div v-loading="loading"></div>
</template>
<script setup>
import { useToggle } from '@vueuse/core';
const [loading, toggleLoading] = useToggle(false)
const loadList = async () => {
try {
toggleLoading(true)
// xxx
} catch (error) {
// xxx
} finally {
toggleLoading(false)
}
}
</script>
useAsyncState(获取异步状态)
响应式获取异步状态。不会阻塞 setup
函数,在 promise
完成后,将自动触发。
<template>
<div v-loading="isLoading">
<div @click="onRefresh">Refresh</div>
</div>
</template>
<script setup>
import axios from 'axios'
import { useAsyncState } from '@vueuse/core'
const { state, isReady, isLoading, execute: loadList } = useAsyncState(
axios
.get('https://jsonplaceholder.typicode.com/todos/1')
.then(t => t.data),
{ id: null },
)
async function onRefresh() {
// xxx
await loadList()
}
</script>
useMouse(获取鼠标当前位置)
<template>
<div>
<p>X: {{ mouse.x }}, Y: {{ mouse.y }}</p>
</div>
</template>
<script setup>
import { useMouse } from '@vueuse/core';
const mouse = useMouse();
</script>
useWindowSize(获取窗口尺寸)
<template>
<div>
<div>{{ width }} - {{ height }}</div>
</div>
</template>
<script setup>
import { useWindowSize } from "@vueuse/core";
const { width, height } = useWindowSize();
</script>
useLocalStorage(本地存储)
<script setup>
import { useLocalStorage } from '@vueuse/core';
// 获取
const name = useLocalStorage('name', ''); // 第一个参数是键名,第二个参数是默认值
console.log(name.value)
// 设置
useLocalStorage('name', '').value = 'a';
// 清除
useLocalStorage('name', '').value = null;
// 或者使用 remove 方法 name.remove();
</script>
useClipboard(剪切板功能)
<template>
<div>
<input v-model="input" type="text" />
<button @click="copy(input)">Copy</button>
</div>
</template>
<script setup>
import { useClipboard } from "@vueuse/core";
const input = ref("");
// text: 复制的内容; copy: 复制函数; isSupported: 当前的浏览器是否支持这个api
const { text, copy, isSupported } = useClipboard();
</script>
useFullscreen(全屏)
<template>
<button @click="toggle">全屏</button>
</template>
<script setup>
import { useFullscreen } from "@vueuse/core";
const { isFullscreen, toggle } = useFullscreen();
</script>
useEventListener(监听事件)
useEventListener
监听事件后,组件卸载时自动调用removeEventListener
,不用担心注册多个事件而导致内存泄露的问题。
<template>
<div>
<div ref="element">useEventListener</div>
</div>
</template>
<script setup>
import { useEventListener } from "@vueuse/core";
const element = ref(null);
useEventListener(element, "click", () => {
console.log("监听点击事件");
});
</script>
useTransition(值之间的过渡)
我们可以使用 useTransition
来过渡整个数字数组,这在处理位置或颜色时很有用。
处理颜色的一个绝招是使用一个计算属性将RGB值格式化为正确的颜色语法。
<template>
<h2 :style="{ color: color } "> COLOR CHANGING </h2>
</template>
<script setup>
import { useTransition, TransitionPresets } from '@vueuse/core'
const source = ref([0, 0, 0])
const output = useTransition(source, {
duration: 3000,
transition: TransitionPresets.easeOutExpo,
})
const color = computed(() => {
const [r, g, b] = output.value
return `rgb(${r}, ${g}, ${b})`
})
source.value = [255, 0, 255]
</script>
useDebounceFn(防抖)
<template>
<div>
<div>{{ counter }}</div>
<button @click="addNum">add</button>
</div>
</template>
<script lang="ts" setup>
import { useDebounceFn } from "@vueuse/core";
const counter = ref(0);
const handleAddFun = () => {
counter.value += 1;
};
const addNum = useDebounceFn(handleAddFun, 300, { maxWait: 5000 });
</script>