Vue3-tsx 实现函数式 loading

249 阅读1分钟

前言

  • ui:tailwindcss

原理

  1. 利用 vue 的 h 函数 + tsx 语法定义一个 loading 组件(全局蒙层 + loading 动画)
// components/LoadingOverlay.tsx
import { defineComponent, h } from "vue";

const LoadingOverlay = defineComponent({
  props: {
    show: Boolean,
    text: String,
  },
  setup(props) {
    return () =>
      props.show
        ? h( 
            "div", 
            {
              class: "fixed inset-0 bg-gray-800 bg-opacity-50 flex justify-center items-center gap-2 z-50",
            },
            [
              h(
                "div", 
                {
                  class:
                    "animate-spin rounded-full h-10 w-10 border-t-4 border-b-4 border-white",
                }
              ),
              h("div", { class: "text-white" }, props.text),
            ]
          )
        : null;
  },
});

export default LoadingOverlay;
  1. 通过 render + h 将 loading 渲染到界面中
// hooks/useLoading.ts
import { ref, reactive, h, render } from "vue";
import CustomLoading from "@/components/CustomLoadingMask";

export default function useLoading() {
  const loadingContainer = ref(document.createElement("div"));

  const state = reactive({
    show: false,
    text: "加载中…",
  });

  const show = (text?: string) => {
    state.show = true;
    if (text) state.text = text;
    if (!loadingContainer.value.parentNode) {
      document.body.appendChild(loadingContainer.value);
    }
    render(
      h(CustomLoading, { show: state.show, text: state.text }),
      loadingContainer.value
    );
  };

  const hide = () => {
    state.show = false;
    state.text = "加载中…";
    render(null, loadingContainer.value);
  };

  return { show, hide };
}

使用


  const { show, hide } = useLoading();
  
  async function doSomething() {
    show("正在加载数据表…");
    try {
        ...
    } catch (e) {
        console.log(e);
    } finally {
        hide();
    }
  }

效果

image.png