大家好,我是 vue-hooks-plus
的作者,这里和大家分享一下属于 Vue3 的方便快捷的申请形式是怎么样的。
Vue3
当初曾经越来越多小伙伴用上了,在很多技术群中对于 Vue3
的评估是很高的,在技术博客、群里也会见到很多小伙伴展现本人的 Vue3
代码块以及对 Vue3
我的项目搭建的一些心得。
置信大部分我的项目采纳了 Vite+Vue3
开发,联合网上的资源我发现对于我的项目整体大架构,比方 状态治理 pinia
、开发构建 Vite
、UI 框架 Element-plus
、Vant
、Antd-vue
等支流框架,网络申请 axios
曾经有很成熟的搭建应用计划了, 咱们搞业务开发,基本上围绕着网络申请打交道,这里和大家聊聊鲜为人知的、好保护、品质牢靠的业务 API 申请 🫣。
📄 列出我所知的申请应用的计划
- 二次封装
axios
、文件夹对立治理 API 申请,返回一个Promise
,在组件中应用链式调用 - 二次封装
axios
、文件夹对立治理 API 申请,返回一个Promise
,在组件中应用async/await
应用 - 二次封装 axios、全局注入 axios, 组件内间接调用中这个实例去传参数调用
- 间接应用 axios 申请(反复繁冗的代码,不利于保护,这里只做举例,不举荐 ❌)
我置信很多小伙伴都属于以上的应用计划,我会一一和大家剖析,谈一下对于 Vue3 网络申请
这块的见解。
🔍 剖析
二次封装 Axios
const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_SCREEN_BASE_URL,
timeout: 1_000 * 10
});
// ... 省略拦截器
治理 API 的文件夹
export function getData(params,options){return new Promise((resolve, reject) => {
axiosInstance({
url,
params,
...options,
})
.then((res) => {resolve(res?.data?.data);
})
.catch((err) => {reject(err);
});
}
}
链式调用,比拟传统
const data = ref()
getData({...xxx},{...xxx}).then((res)=>{
// ... 这里解决数据
data.value = res.data
}).catch(err=>{// ...xxx})
Async/Await 调用,比拟优雅
const data = ref()
onMounted(async () => {const res = await getData({...x},{...x})
data.value = res
}
Provide/Inject 调用,和链式用法基本一致,只是代码量稍少。
main.ts
import axios from 'axios'
import VueAxios from 'vue-axios'
app.use(VueAxios, axios)
app.provide('axios', app.config.globalProperties.axios)
App.vue
const axios: any = inject('axios') // inject axios
axios({url,data,... 其余配置}).then() // 同上
🧑💻 认识
我置信很多小伙伴会比拟喜爱第二种的 async/await
的语法糖,比拟优雅,简洁。
在当今前端业务越来越简单的环境下,网络申请场景也会变得复杂起来,比方
- 屡次申请拿
上一次
的数据作为参数体
。 - 某个值变动了又须要
从新申请
。 -
或者某个值
满足条件
才开始申请。对于链式调用来说,是十分不利于代码浏览的,整个业务组件充斥着反复代码,十分不利于保护。
对于
async/await
仿佛很好的解决了以上的问题,- 第一个,await 拿上一次
申请参数
的很不便啊! ✅。 - 第二个,某个值变动了须要从新申请,这里很多小伙伴会想到我把这个申请封装起来,放进
watch
外面监听执行 ✅ - 第三个,在封装的申请函数中退出判断条件是否执行 ✅
上述场景多个组件, 多次重复操作,这样文件一多,也存在很多代码反复 ❌
- 第一个,await 拿上一次
✅ 正确思路
咱们须要将这些反复的操作进行封装成 hook
,把依赖申请,判断条件是否发动申请这些封装成起来,有执行 async/await
的办法,又有这些依赖申请的功能模块一起联结应用,而用户只须要传递须要开启的性能配置即可;
什么是 hook
?
在 React
中的意思是将一个以 use
结尾,含react
状态和 effect 纯函数的内部代码挂入到它的节点当中。
在 Vue
中,我认为将 Vue
的 effect,如 ref、watch、watchEffect 的内部代码放入 vue 中执行,也是挂入 hook
。
这里咱们命名 useRequest
const useRequest = (service,option)=>{const data = ref()
const run = async ()=>{const res = await service()
data.value = res
}
// 是否满足条件
if(option.ready){run()
}
// 依赖从新申请
watch(option.deps,()=>{run()
})
return {
data,
run
}
}
以上的写法是 hook 写法,外面应用到了 ref
、watch
,很多小伙伴从 Vue2
过渡来 Vue3
的,对这块这样应用的接触的很少。应用高质量牢靠的申请 hook
我置信前面会成为 Vue3
开发的一个趋势,上面我展现一下业务中的应用流程,展示它的魅力 😉
<template>
<div> 读取值:{{data}}</div>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
import {useRequest} from '..'
//、、、、、业务代码
//、、、、、业务代码
const {data} = useRequest(() => getData(), {
ready:true
deps:[依赖其余响应式对象]
})
</script>
比方这块业务代码,用户间接拿到解决好的申请的 data
,它是一个响应式,所以业务层省去了一个申明响应式对象来保留数据的代码,ready
判断条件,业务层又被砍去一个条件判断函数,依赖刷新
,砍去书写watch
的代码,用户只须要关注配置即可,咱们会发现它是通过 run 办法调用触发申请
的,那么,咱们的防抖、节流函数只须要作用于 run
函数即可,所以这样的做法,是不是很简洁。
这一块的拓展性极强,你能够拓展 loading
状态、params
等进来。因为应用 async/await
, 所以咱们治理的申请 API 返回一个 promise
对象即可,意味着axios
和 request
这些都兼容,齐全将申请这块的功能性的模块从业务层脱离,用户只须要关注配置和 API 接口!
const {data} = useRequest(() => getData(), {
// 防抖
// 节流
// ready
// 依赖刷新
// 格式化申请
...
})
几行配置下来,给人的感觉就清新,而且保护起来那叫一个舒服。
🏃 Use
- 二次封装
axios
或者 其余申请工具 - 封装申请
hook
钩子 - 应用文件治理
API 接口
,👆写的应用一个函数返回一个promise
即可 - 业务层应用
hook
传配置即可
📌 额定 tip
封装带有 ts 提醒的 axios axiosInstance
和大家罕用的一样,AxiosRequestConfig 类型从 axios
导出。留神: 因为这里没写拦截器,所以返回了一个多余的 new Promise
让大家直观的看到,只须要承受返回的一个 Promise 对象
即可,实际上不论是 axios
还是 request
自身返回的都是 Promsie 对象
的。
const request = <ResponseType = unknown>(
url: string,
options?: AxiosRequestConfig<unknown>,
): Promise<ResponseType> => {return new Promise((resolve, reject) => {
axiosInstance({
url,
...options,
})
.then((res) => {resolve(res?.data?.data);
})
.catch((err) => {reject(err);
});
});
};
须要配合拦截器截取 res.data.data
const request = <ResponseType = unknown>(
url: string,
options?: AxiosRequestConfig<unknown>,
): Promise<ResponseType> => {return axiosInstance({url,...options})
};
申请函数示例 AnalysisReportType
为 数据返回预约的 data
类型,反对 ts
export async function getListReports(
params?: {
reportGroup?: string | null;
sortCol?: 'visitUv' | 'uploadFileTime';
sortType?: string;
reportName?: string;
},
) {
return request<AnalysisReportType>('/platform/report/listReports', {params: { ...params, sortType: 2},
});
}
业务组件中
const {data} = useRequest(()=>getListReports(),{
ready:true,
... 其余配置
})
👋 拿来吧你
因为 vueuse 没有这块的性能,我针对业务层写了一个 vue-hooks-plus
库,残缺的测试用例笼罩,高质量牢靠,外面涵盖封装了一个 useRequest
钩子,本人公司曾经用上,安全可靠,满足业务 99% 需要,并且反对按需引入,以下展现基本功能,更多具体见 API 文档 👇
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,
formatResult?:(response:TData)=>any,
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 保姆级业务开发教程
useRequest 国内文档地址
Github 地址
喜爱的小伙伴棘手点个 star 🌟,多多反对!