白筱汐

想都是问题,做都是答案

0%

自定义一个vue useFetch

自定义hooks

在 vue2 里面有一些公共的逻辑,我们可以使用 mixins(混入)。vue3 里面的逻辑复用,官方推荐的方式包括自定义组合式函数,也就是自定义一些hooks,官方案例

vue官方也有一些好用的 hooks 工具集,vueuse 其中的一些 hook 在 nuxt3 里面也是开箱即用,例如 useFetch。

useFetch 可以发送一个 fetch 请求,并且返回响应式的数据。简化我们创建响应式数据并且请求赋值的流程,非常的方便。

自定义一个 useFetch

通常我们的前端项目都使用 axios 来封装发送请求,但是 useFetch 里面发送请求的却是其他的库 ofetch,具体可以查看 nuxt3 里面 useFetch 的说明。

所以我就封装了一个基于自己的项目的 useFetch 处理请求的方法。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import {ref, watch} from 'vue';
import {ElMessage} from "element-plus";

export const useFetch = (fetch, {
immediate = true, // 是否立即发送请求
effectArray = [], // 副作用依赖项,watch 监听,以便重新发送请求
beforeFetch, // 请求发送之前执行的回调
afterFetch, // 请求发送之后执行的回调
onSuccess, // 成功的回调函数
onError, // 错误的回调函数
updateDataOnError = false, // 接口出错时是否更新数据
initialData = null // 初始化数据响应式数据,可用于页面渲染
} = {
immediate: true,
updateDataOnError: false,
effectArray: [],
initialData: null
}) => {

const isLoading = ref(false) // 是否正在加载中
const isFinished = ref(false) // 请求是否结束
const data = ref(initialData) // 根据 initialData 创建的响应式的数据
const response = ref(null) // 响应式的接口返回的 response
const error = ref(null) // 响应式的请求错误数据

const execute = () => {
beforeFetch && beforeFetch()
isLoading.value = true
isFinished.value = false
error.value = null
fetch().then(res => {
response.value = res
if (res?.status === '00000') {
onSuccess && onSuccess(res)
data.value = res.data
} else {
ElMessage.error(res?.message)
if (updateDataOnError) {
data.value = null
}
}
}).catch(e => {
onError && onError(e)
error.value = e
}).finally(() => {
afterFetch && afterFetch()
isLoading.value = false
isFinished.value = true
})
}

if (immediate) {
execute()
}

// 写一个防抖函数,延迟 触发 execute,防止重复
const debounceExecute = debounce(execute, 100)

// 监听依赖项发生变化,重新发起请求
if (effectArray.length > 0) {
watch(effectArray, debounceExecute)
}

return {
isLoading,
isFinished,
response,
error,
data,
execute
}
}

使用案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const page = reactive({
pageNum: 1,
pageSize: 10
})

// 假设需要响应式的 table 列表数据
const initialData = reactive({
list: [],
total: 0
})

// 此处省略了 axios 实例的一些配置
const {data} = useFetch(() => axios.post('/getList',{pageNum: page.pageNum,pageSize: page.pageSize}), {
initialData,
immediate: false,
effectArray: [() => page.pageNum,() => page.pageSize]
})

大家可以根据自己的项目需求修改一些配置。 类似的也可以根据 react 里面 useState, useEffect 创建一个 react 版本的 useFetch。ahooks 也是不错的导师,里面可以学到很多思路。