描述
我们在业务中,经常要异步请求数据,来渲染我们的页面,而且为了代码和逻辑的复用,我们可以封装成一个hooks
技术栈
- vue3
- typescript
import { toRefs, reactive, onMounted } from 'vue'
type Service<R = any, P extends any[] = any[]> = (...args: P) => Promise<R>
type OptionsType = {
/** 是否手动调用 */
manual?: boolean
/** 初始化数据 */
initialData?: any
/** 成功回调 */
onSuccess?: () => void
/** 失败回调 */
onError?: (e: Error | null) => void
/** 其他属性 */
[propName: string]: any
}
type StateType<D> = {
data: D
loading: boolean
error: Error | null
}
/**
* useAsync
* @param {Promise} pro 异步操作
* @param {Object} options 参数
* @param {Boolean} [options.manual=false] 是否手动调用
* @param {Any} options.initialData 初始化数据
* @param {Function} options.onSuccess 成功回调
* @param {Function} options.onError 失败回调
*/
export function useAsync<T = any>(pro: Service<T>, options: OptionsType = {}) {
const {
manual = false,
initialData,
onSuccess = () => {}, // eslint-disable-line
onError = console.log
} = options
const state: StateType<T> = reactive({
data: initialData || null,
error: null,
loading: false
})
const run = async () => {
state.error = null
state.loading = true
try {
const result = await pro()
state.data = result
onSuccess()
} catch (err) {
onError(err)
state.error = err
}
state.loading = false
}
onMounted(() => {
!manual && run()
})
// 从外部主动改变数据
function mutate(data: T) {
state.data = data
}
return {
...toRefs(state),
run,
mutate
}
}
复制代码
使用
<template>
<ul>
<li v-for="(item, index) in list" :key="index">{{item.name}}</li>
</ul>
</template>
<script>
import { defineComponent, ref } from 'vue'
function getUsers() {
return new Promise(resolve => {
setTimeout(() => {
resolve([
{ name: 'foo' },
{ name: 'bar' },
{ name: 'baz' }
])
}, 1000)
})
}
export default defineComponent({
setup() {
const { data: list } = useAsync(
() => {
return getUsers()
},
{
initialData: []
}
)
return {
list
}
}
})
</script>
复制代码
总结
useAsync插件来自ant-simple-pro里面,ant-simple-pro有很多用vue3+ts开发的插件。ant-simple-pro简洁,美观,快速上手,支持3大框架。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END