Vue3使用hook封装常见的几种异步请求函数场景,让开发更丝滑

初始化一个请求函数,然后根据初始参数,立即发送请求,返回请求结果,并且返回请求回调函数,方便我们根据新的参数再次调用。
首页 新闻资讯 行业资讯 Vue3使用hook封装常见的几种异步请求函数场景,让开发更丝滑

🚀 立即请求函数

我们期望的场景是,

  • 初始化一个请求函数,然后根据初始参数,立即发送请求

  • 返回请求结果,并且返回请求回调函数,方便我们根据新的参数再次调用

  • 要求返回值包含加载中状态,错误信息以及正常的数据类型。

我的实现过程如下:

定义具体的数据返回值签名

interfaceFetch<T>{
  loading:boolean,value?: T,// 具体的返回类型是泛型error?: string
}

完整的签名如下

exportdeclarefunctionuseFetch<T,Params>(fn:(args: Params)=>Promise<T>,initParams: Params):[Fetch<T>,(params: Params)=>Promise<unknown>]

函数实现如下:

export const useFetch=<T,Params>(fn:(args: Params)=>Promise<T>,initParams: Params):[Fetch<T>,(params: Params)=>Promise<T>]=>{// 定义基础的数据格式constdata=reactive<Fetch<T>>({
    loading:true,value:undefined,error:undefined})asFetch<T>// 这里会报错:T类型无法赋值给UnwrapRef<T>类型// 我不懂为啥,UnwrapRef是vue的深层响应式类型的声明// 这里导致我无法默认的类型赋值,不符合直觉,可能是我ts太菜了// 懂的大佬评论区带带我吧// 定义请求回调const callback=(params: Params): Promise<T>=>new Promise((resolve,reject)=>{data.loading=truefn(params).then(result=>{data.value=resultasanyresolve(result)}).catch(error=>{data.error=error
        reject(error)}).finally(()=>data.loading=false)})// 立即执行watchSyncEffect(()=>{
    callback(initParams)})return[data,callback]}

我们验证下

<script setup lang="ts">import{ reactive }from'vue';import{ useFetch }from'./hooks/index';const fn=()=>new Promise((resolve)=>{
  setTimeout(()=>resolve({data:[],msg:'',code:200}),1000)})const[data,fetch]=useFetch<unknown,object>(fn,{})</script><template><h4>公众号:萌萌哒草头将军</h4><!-- 加载中时用css禁用按钮 --><button
    :style="{'pointer-events': data.loading ? 'none' : 'auto'}"@click="fetch({})">{{data.loading ?'laoding...':'fetch'}}</button><h1 v-if="data.loading">loading...</h1><h1 v-else>{{data.value}}</h1></template>

fetch.giffetch.gif

页面刷新后立即发出请求了!

🚀 手动请求函数

我们期望的场景是,

  • 初始化一个请求函数

  • 返回请求回调函数,方便我们调用

  • 要求返回值包含加载中状态,错误信息以及正常的数据类型

这个的实现和上面类似,我们不需要初始参数和类型,也不用立即执行,

完整的签名如下

exportdeclarefunctionuseFetch<T>(fn:(args: unknown)=>Promise<T>):[Fetch<T>,(params: unknown)=>Promise<T>]

实现如下:

export const useFetchFn=<T>(fn:(args: unknown)=>Promise<T>):[Fetch<T>,(params: unknown)=>Promise<T>]=>{
  
  constdata=reactive<Fetch<T>>({
    loading:false,// 默认为falsevalue:undefined,error:undefined})asFetch<T>const callback=(params: unknown): Promise<T>=>new Promise((resolve,reject)=>{data.loading=truefn(params).then(result=>{data.value=resultasanyresolve(result)}).catch(error=>{data.error=error
        reject(error)}).finally(()=>data.loading=false)})return[data,callback]}

验证如下:

<script setup lang="ts">import{ reactive }from'vue';import{ useFetchFn }from'./hooks/index';const fn=()=>new Promise((resolve)=>{
  setTimeout(()=>resolve({data:[],msg:'',code:200}),1000)})const[data,fetch]=useFetchFn<unknown>(fn)</script><template><h4>公众号:萌萌哒草头将军</h4><!-- 加载中时用css禁用按钮 --><button
    :style="{'pointer-events': data.loading ? 'none' : 'auto'}"@click="fetch({})">{{data.loading ?'laoding...':'fetch'}}</button><h1 v-if="data.loading">loading...</h1><h1 v-else>{{data.value}}</h1></template>

fetchfn.giffetchfn.gif

页面刷新后没有发出请求,点击按钮之后才发出请求!

🚀 自动请求函数

我们期望的场景是,

  • 初始化一个请求函数,然后根据初始参数,立即发送请求

  • 当参数发生变化时,自动根据最新参数发送请求

  • 要求返回值包含加载中状态,错误信息以及正常的数据类型。

这个的实现和立即请求函数类似,只需要监听参数的变化,

完整的签名如下

exportdeclarefunctionuseFetch<T,Params>(fn:(args: Params)=>Promise<T>,initParams: Params):Fetch<T>

实现如下:

export const useAutoFetch=<T,Params>(fn:(args: Params)=>Promise<T>,initParams: Params):Fetch<T>=>{
  
  constdata=reactive<Fetch<T>>({
    loading:true,value:undefined,error:undefined})asFetch<T>const callback=(params: Params): Promise<T>=>new Promise((resolve,reject)=>{data.loading=truefn(params).then(result=>{data.value=resultasanyresolve(result)}).catch(error=>{data.error=error
        reject(error)}).finally(()=>data.loading=false)})// 如果不需要立即执行,可没有这步const effects=watchSyncEffect(()=>{
    callback(initParams)})// 自动监听参数变化const effects=watch([initParams],()=>callback(initParams))// 卸载页面时,关闭监听onUnmounted(()=>effects())returndata}

我们验证下功能

<script setup lang="ts">import{ reactive,watch }from'vue';import{ useAutoFetch }from'./hooks/index';const fn=()=>new Promise((resolve)=>{
  setTimeout(()=>resolve({data:[],msg:'',code:200}),1000)})const params=reactive({
  age:9})constdata=useAutoFetch<unknown,object>(fn,params)watch(params,()=>console.log(params))</script><template><h4>公众号:萌萌哒草头将军</h4><div>{{ params.age }}</div><!-- 加载中时用css禁用按钮 --><button
    :style="{'pointer-events': data.loading ? 'none' : 'auto'}"@click="() => params.age++">{{data.loading ?'laoding...':'change params'}}</button><h1 v-if="data.loading">loading...</h1><h1 v-else>{{data.value}}</h1></template>

auto.gifauto.gif

每次当我们改变参数时自动发送请求。

23    2023-07-06 08:10:57    Vue3 参数 请求