我们期望的装常种异场景是,
我的见的景让实现过程如下:
定义具体的数据返回值签名
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>
fetch.gif
页面刷新后立即发出请求了!
我们期望的场景是,
这个的实现和上面类似,我们不需要初始参数和类型,也不用立即执行,
完整的签名如下
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>
fetchfn.gif
页面刷新后没有发出请求,点击按钮之后才发出请求!
我们期望的场景是,
这个的实现和立即请求函数类似,只需要监听参数的变化,
完整的签名如下
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>
auto.gif
每次当我们改变参数时自动发送请求。
责任编辑:武晓燕 来源: 萌萌哒草头将军 Vue3参数请求(责任编辑:百科)
《名侦探柯南:贝克街的亡灵》预售正式开启 高能双线推理重磅来袭
中盈盛达融资担保(01543.HK)完成发行2.60亿元公司债 票面利率为4.60%
评价结果显示:零售业务对商业银行收益可持续能力的贡献不断增强