Loading状态按钮

方法1:hook.ts
import { Ref, ref } from 'vue';

type TApiFun<TData, TParams extends Array<any>> = (...params: TParams) => Promise<TData>;

interface AutoRequestOptions {
   // 定义一下初始状态
  loading?: boolean;
  // 接口调用成功时的回调
  onSuccess?: (data: any) => void;
}

type AutoRequestResult<TData, TParams extends Array<any>> = [Ref<boolean>, TApiFun<TData, TParams>];

/* 控制loading状态的自动切换hook */
export function useAutoRequest<TData, TParams extends any[] = any[]>(fun: TApiFun<TData, TParams>, options?: AutoRequestOptions): AutoRequestResult<TData, TParams> {
  const { loading = false, onSuccess } = options || { loading: false };

  const requestLoading = ref(loading);

  const run: TApiFun<TData, TParams> = (...params) => {
    requestLoading.value = true;
    return fun(...params)
      .then((res) => {
        onSuccess && onSuccess(res);
        return res;
      })
      .finally(() => {
        requestLoading.value = false;
      });
  };

  return [requestLoading, run];
}

api/index.ts

export function submitApi(text: string) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // 模拟接口调用有概率出错
      if (Math.random() > 0.5) {
        resolve({
          status: "ok",
          text: text,
        });
      } else {
        reject(new Error("不小心出错了!"));
      }
    }, 3000);
  });
}

使用:index.vue

<script setup name="Index" lang="ts">
import { useAutoRequest } from "./hook";
import { Button } from "ant-design-vue";
import { submitApi } from "@/api";

const [loading, submit] = useAutoRequest(submitApi);

function onSubmit() {
   submit("aaa").then((res) => {
    console.log("res", res);
  });
}
</script>

<template>
  <div class="col">
    <Button :loading="loading" @click="onSubmit">提交</Button>
  </div>
</template>
方法2:hook2.ts
import type { Ref } from "vue";
import { ref } from "vue";

type AutoLoadingResult = [
  Ref<boolean>,
  <T>(requestPromise: Promise<T>) => Promise<T>
];

/* 在给run方法传入一个promise,会在promise执行前或执行后将loading状态设为true,在执行完成后设为false */
export function useAutoLoading(defaultLoading = false): AutoLoadingResult {
  const ld = ref(defaultLoading);

  function run<T>(requestPromise: Promise<T>): Promise<T> {
    ld.value = true;
    return requestPromise.finally(() => {
      ld.value = false;
    });
  }

  return [ld, run];
}

使用:

<script setup name="Index" lang="ts">
// import { useAutoRequest } from "./hook";
import { useAutoLoading } from "./hook2";
import { Button } from "ant-design-vue";
import { submitApi, cancelApi } from "@/api";

// const [loading, submit] = useAutoRequest(submitApi);

const [commonLoading, fetch] = useAutoLoading();

function onSubmit() {
  fetch(submitApi("submit")).then((res) => {
    console.log("res", res);
  });
}

function onCancel() {
  fetch(cancelApi("cancel")).then((res) => {
    console.log("res", res);
  });
}
</script>

<template>
  <div class="col">
    <Button type="primary" :loading="commonLoading" @click="onSubmit">
      提交
    </Button>
    <Button :loading="commonLoading" @click="onCancel">取消</Button>
  </div>
</template>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值