一、是什么
Vue3引入的组合式API 带来了新的复用逻辑的方式,我们可以把重复的有状态的逻辑抽取成函数,供页面调用,而且这些函数还能被组合使用,更加灵活。
VueUse就是这样一个基于组合式API的函数库,封装了很多常见的,可复用的函数,支持Vue2,Vue3,Nuxt,可以理解为Vue世界的lodash,开箱即用,非常方便。
二、现状
作者:AnthonyFu,Vue、Vite团队核心成员
官网:vueuse.org/
中文地址:www.vueusejs.com/
Github:github.com/vueuse/vueu...
注: 官网最新版本V10.7.2;中文地址非官方,保留了官方英文网站的原文,翻译文档最新版本V9.13.0。Github仓库Start 17.9k,更新频繁,非常活跃。
三、功能
核心包有140+组合式函数,此外还提供了10个扩展插件,共约有290+函数
核心包中提供了12种类型的函数,如下所示:
State:管理用户状态(如:全局、本地存储、会话存储)
Elements:元素处理相关(如:元素拖拽、元素可见性、窗口尺寸)
Browser:浏览器相关(如:更新页面title、媒体查询、剪贴板)
Sensors:监听不同的DOM事件、输入事件和网络事件等
Network:网络请求相关
Animation:过渡、超时和计时功能
Component:提供了不同组件方法的简写
Watch:提供一些监听器(如:监听promise后的变化、防抖监听、节流监听)
Reactivity:响应式函数相关
Array:响应式的数组处理
Time:提供响应时间格式化功能
Utilities:通用函数,如 节流、防抖等
扩展插件:Electron、Firebase、Head、Integrations、Math、Motion、Router、RxJS、SchemaOrg、Sound
核心功能都在packages/core文件夹下。
四、使用
- 安装
js
// npm、yarn、pnpm 都可以,安装核心包 @vueuse/core
npm i @vueuse/core
yarn add @vueuse/core
pnpm add @vueuse/core
- 使用
作为函数直接调用:比如 const { toggle } = useFullScreen(),这也是我们最常用的方式。
作为组件使用 :部分功能提供,比如<UseFullscreen><UseFullscreen>
。
作为函数直接调用时,可以接收响应式参数 ,大多数函数都会返回一个refs对象,可以使用对象解构来获取需要的内容。函数通常以use开头。
VueUse提供了如上两种使用方法,下面分享两个常用的函数useFullscreen、useStorage来详细说明。
- useFullscreen
封装了全屏相关的功能, 功能文档:vueuse.org/core/useful...
函数式调用方法:
html
<span @click="toggle">
<VbenSvgIcon :size="18" icon="fullscreen" v-if="!isFullscreen" />
<VbenSvgIcon :size="18" icon="notfullscreen" v-else />
</span>
js
import { useFullscreen } from '@vueuse/core'
const { toggle, isFullscreen } = useFullscreen()
这是对整个页面全屏,除此之外还支持传入某个元素,这样只会对该元素区域进行全屏显示,如下:
html
<div>
isFullscreen: {{ isFullscreen }}
<button @click="toggle">开启全屏</button>
<div ref="el" style="background: yellow;">把我全屏</div>
</div>
js
import { useFullscreen } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { isFullscreen, toggle } = useFullscreen(el)
组件式用法, 除了安装@vueuse/core核心包之外,还需要安装 @vueuse/components,即
js
pnpm add @vueuse/core @vueuse/components
html
<UseFullscreen v-slot="{ toggle }">
<button @click="toggle">
Go Fullscreen
</button>
</UseFullscreen>
js
import { UseFullscreen } from '@vueuse/components'
源码
源码位置:packages/core/useFullscreen
有四个文件:component.ts、demo.vue、index.md、index.ts
component.ts:封装函数的无渲染组件,所以我们能以组件的方式调用
demo.vue:示例
index.md:说明文件
index.ts:核心代码(100+行)
函数声明:
js
export declare function useFullscreen(
target?: MaybeElementRef,
options?: UseFullscreenOptions,
): {
isSupported: ComputedRef<boolean>
isFullscreen: Ref<boolean>
enter: () => Promise<void>
exit: () => Promise<void>
toggle: () => Promise<void>
}
核心源码:
js
export function useFullscreen(
target?: MaybeElementRef,
options: UseFullscreenOptions = {},
) {
// ...
const targetRef = computed(() => unrefElement(target) ?? document?.querySelector('html'))
const isFullscreen = ref(false)
// 可以学习这种写法
const requestMethod = computed<'requestFullscreen' | undefined>(() => {
return [
'requestFullscreen',
'webkitRequestFullscreen',
'webkitEnterFullscreen',
'webkitEnterFullScreen',
'webkitRequestFullScreen',
'mozRequestFullScreen',
'msRequestFullscreen',
].find(m => (document && m in document) || (targetRef.value && m in targetRef.value)) as any
})
// ...
async function exit() {
if (!isSupported.value || !isFullscreen.value)
return
if (exitMethod.value) {
if (document?.[exitMethod.value] != null) {
await document[exitMethod.value]()
}
else {
const target = targetRef.value
// @ts-expect-error - Fallback for Safari iOS
if (target?.[exitMethod.value] != null)
// @ts-expect-error - Fallback for Safari iOS
await target[exitMethod.value]()
}
}
isFullscreen.value = false
}
async function enter() {
if (!isSupported.value || isFullscreen.value)
return
if (isElementFullScreen())
await exit()
const target = targetRef.value
if (requestMethod.value && target?.[requestMethod.value] != null) {
await target[requestMethod.value]()
isFullscreen.value = true
}
}
async function toggle() {
await (isFullscreen.value ? exit() : enter())
}
return {
isSupported,
isFullscreen,
enter,
exit,
toggle,
}
}
- useStorage
VueUse里面封装的useStorage有很多优点,易于使用。useLocalStorage和useSessionStorage内部直接调用的useStorage,默认存储方式为localStorage和sessionStorage。
- 使用useStorage会直接返回一个响应式ref,直接改变ref的值,本地存储也会同步更新。
2.保存数据数据时也没有限制只能是string类型,支持多种类型,如对象、布尔、数字等。
3.可以直接更改对象的某个字段,不需要像用原生API一样整体替换。
4.内部监听了storage事件,所以直接面板操作,也能响应式更新。
html
<div>
storage: {{ state }}
<button @click="edit">修改</button>
<button @click="clear">清除</button>
</div>
js
import { useStorage } from '@vueuse/core'
// 不限制存储值的类型
const state = useStorage('liufeifei-test', [1,2,3])
// 返回一个ref
console.log('state', state)
const edit = () => {
// 可以直接更新对象字段
state.value[1] = 222
}
const clear = () => {
state.value = null
}
调用useStore返回一个ref
localStorage存储成功
js
import { useStorage } from '@vueuse/core'
// 如果存储的字段已经有值,不会被更新
localStorage.setItem('liufeifei-test', '{ "a": 1 }')
const state = useStorage('liufeifei-test', { a: 111, b: 222 })
console.log('state', state.value) // Proxy {a : 1}
// 可以通过配置 mergeDefaults: true; 合并值
const state1 = useStorage('liufeifei-test', { a: 111, b: 222 }, localStorage, { mergeDefaults: true })
console.log('state1', state1.value) // Proxy { a : 1, b: 222 }
源码
源码位置:packages/core/useStorage ( 核心代码200+行)
五、其他
VueUse封装了非常多实用功能,如:剪切板(useClipboard)、防抖(useDebounceFn), 设置网页的title(useTitle),监听事件(useEventListener, 页面卸载可以自动帮助我们删除事件监听,不用我们手动删除)等等,自己封装hooks前,可以去官网看看有没有已经封装好的,提升开发效率。
VueUse还有很好的交互文档和功能演示 ,TS编写,每个功能的核心源码也都比较少,比较好读,除了可以使用其封装的功能外,我们还可以看其源码学习功能封装技巧,学习优秀的编码习惯。