浅谈我为什么不使用 VueUse,而选择造轮子
💬 前言
想想一名React
开发开发Vue
是什么体验。就在今天初含泪写多一个vue
项目,不是转,是写多!选用的是vue3+vite开发。Composition API
让我得心应手。之前react开发选的是react16,ahooks
是我接触最多的hooks
库了,很贴合我的业务。在使用vue3的时候开发的时候选取了 vueuse
。
👨🏫 问题
在前端开发中和请求打交道是最多的,大多数业务都是restful api架构,我们拿到数据做处理,当前流行的框架配备着状态机制,在依赖变化时进行重新请求等。 vueuse
中的 useFetch
和 useAxios
是作为请求的 hook
。useFetch功能比较单一,只有请求体的一些基本功能。useAxios
更多基于axios内置功能的封装,业务中的依赖刷新,防抖,节流,缓存等功能都没有的。这里就有小伙伴问了,那你在 useAxios
上封装这些节流防抖功能就好了,先不说需要侵入式的修改这个钩子,它仅支持axios
,万一项目变成request
呢?
🙋♂️ 解决
ahooks 是前端界大名鼎鼎的 react 的 hooks,它含有更加丰富的功能,能贴合我们更多的业务,其中的 useRequest
是满足我的需求的,但苦于没有vue版本,于是我觉得自己开发一版基于vue3特性的useRequest
。它具备了ahooks的所有功能:
- 自动请求/手动请求
- 轮询
- 防抖
- 节流
- 屏幕聚焦重新请求
- 错误重试
- loading delay
- SWR(stale-while-revalidate)
- 缓存
- 插件式
const {
loading: Ref<boolean>,
data?: Ref<TData>,
error?: Ref<Error>,
params: Ref<TParams || []>,
run: (...params: TParams) => void,
runAsync: (...params: TParams) => Promise<TData>,
refresh: () => void,
refreshAsync: () => Promise<TData>,
mutate: (data?: TData | ((oldData?: TData) => (TData | undefined))) => void,
cancel: () => void,
} = useRequest<TData, TParams>(
service: (...args: TParams) => Promise<TData>,
{
manual?: boolean,
defaultParams?: TParams,
onBefore?: (params: TParams) => void,
onSuccess?: (data: TData, params: TParams) => void,
onError?: (e: Error, params: TParams) => void,
onFinally?: (params: TParams, data?: TData, e?: Error) => void,
...高级功能,更多请见文档
}
);
这个useRequest
请求体允许传入任意promise对象,所以它并不限制是axios还是request,并且功能都是一致的。如果想使用请求库的一些特定功能,我们可以封装那些特定功能成为useRequest
的插件,可以控制在它的生命周期中调用。所以它既体现出包容性又体现出对于单个个体特殊功能的接纳。
插件化的使用
<template>
<div>{{ data?.name ?? '-' }}</div>
<div>{{ data?.age ?? '-' }}</div>
</template>
<script lang="ts" setup>
import { useRequest } from 'vue-hooks-plus'
import { Plugin } from '../../../types'
// 插件
const useFormatter: Plugin<
{
name: string
age: number
},
[]
> = (fetchInstance, { formatter }) => {
return {
onSuccess: () => {
fetchInstance.setData(formatter(fetchInstance.state.data), 'data')
},
}
}
function getUsername(): Promise<{ name: string; age: number }> {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
name: 'yong_git',
age: 18,
})
}, 1000)
})
}
const { data } = useRequest(
() => getUsername(),
{
formatter: () => {
return {
name: 'plugins update',
age: 20,
}
},
},
[useFormatter]
)
</script>
上面实现了一个formatter返回结果的插件,它在请求完成的时候return {name: 'plugins update',age: 20,}
覆盖了请求的结果,更多详情请见文档。
下面是我基于 ahooks
实现的 Vue3
的hooks库 vue-hooks-plus
,测试用例完善,高质量可靠,收获很多,框架的机制所体现出来的独特性让人眼前一亮 🤩。后续还会挑重点hooks详细讲解原理和大家分享。
👋 试试看
大家 star star 🌟🌟 ,感谢支持!
✨ 文档亮相
🥰 靓文分享
大家可以看看这篇关于在 Vue3
中使用 useRequest
在业务代码中发送请求和维护技巧的文章
✨ Vue3开发,或许你需要这样使用请求API