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

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

今天继续上次的内容,使用hook封装几种的异步请求函数场景。

🚀 立即请求函数

我们期望的场景是,

  • 初始化一个请求函数,然后根据初始参数,立即发送请求
  • 返回请求结果,并且返回请求回调函数,方便我们根据新的参数再次调用
  • 要求返回值包含加载中状态,错误信息以及正常的数据类型。

我的实现过程如下:

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

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

完整的签名如下

export declare function useFetch <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>] => {
  // 定义基础的数据格式
  const data = reactive<Fetch<T>>({
    loading: true,
    value: undefined,
    error: undefined
  }) as Fetch<T> // 这里会报错:T类型无法赋值给UnwrapRef<T>类型
  // 我不懂为啥,UnwrapRef是vue的深层响应式类型的声明
  // 这里导致我无法默认的类型赋值,不符合直觉,可能是我ts太菜了
  // 懂的大佬评论区带带我吧
  // 定义请求回调
  const callback = (params: Params): Promise<T> => new Promise((resolve, reject) => {
    data.loading = true
    fn(params)
      .then(result => {
        data.value = result as any
        resolve(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>

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

🚀 手动请求函数

我们期望的场景是,

  • 初始化一个请求函数
  • 返回请求回调函数,方便我们调用
  • 要求返回值包含加载中状态,错误信息以及正常的数据类型

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

完整的签名如下

export declare function useFetch <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>] => {
  const data = reactive<Fetch<T>>({
    loading: false, // 默认为false
    value: undefined,
    error: undefined
  }) as Fetch<T>
  const callback = (params: unknown): Promise<T> => new Promise((resolve, reject) => {
    data.loading = true
    fn(params)
      .then(result => {
        data.value = result as any
        resolve(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>

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

🚀 自动请求函数

我们期望的场景是,

  • 初始化一个请求函数,然后根据初始参数,立即发送请求
  • 当参数发生变化时,自动根据最新参数发送请求
  • 要求返回值包含加载中状态,错误信息以及正常的数据类型。

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

完整的签名如下

export declare function useFetch <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> => {
  const data = reactive<Fetch<T>>({
    loading: true,
    value: undefined,
    error: undefined
  }) as Fetch<T>
  const callback = (params: Params): Promise<T> => new Promise((resolve, reject) => {
    data.loading = true
    fn(params)
      .then(result => {
        data.value = result as any
        resolve(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())
  return data
}

我们验证下功能

<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
})
const data = 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>

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

今天的分享就这些,欢迎大家指正不足的地方,十分感谢

相关文章
|
14天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发
|
20天前
Vue3 项目的 setup 函数
【10月更文挑战第23天】setup` 函数是 Vue3 中非常重要的一个概念,掌握它的使用方法对于开发高效、灵活的 Vue3 组件至关重要。通过不断的实践和探索,你将能够更好地利用 `setup` 函数来构建优秀的 Vue3 项目。
|
21天前
|
JavaScript 搜索推荐 前端开发
Vue SSR 预渲染的广泛应用场景及其优势
【10月更文挑战第23天】Vue SSR 预渲染技术在众多领域都有着广泛的应用价值,可以显著提升网站的性能、用户体验和搜索引擎优化效果。随着技术的不断发展和完善,其应用场景还将不断拓展和深化
37 2
|
23天前
|
JavaScript API
vue3知识点:ref函数
vue3知识点:ref函数
30 2
|
24天前
|
JavaScript API
vue3知识点:自定义hook函数
vue3知识点:自定义hook函数
26 2
|
23天前
|
API
vue3知识点:reactive函数
vue3知识点:reactive函数
26 1
|
24天前
|
JavaScript 前端开发 测试技术
组件化开发:创建可重用的Vue组件
【10月更文挑战第21天】组件化开发:创建可重用的Vue组件
24 1
|
8天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
8天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
8天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。