vue2 & [vue3 ts]全局loading挂载

时间:2024-09-30 11:23:52

vue2

1.新建loading.vue 界面

<template>
  <div class="loading"
       id="loadingPage"
       v-show="show"
       style="pointer-events: none"
  >
    <Spin
        :tip="tipMsg"
        size="large"
        class="spin"
    ></Spin>
  </div>
</template>
<script>
import {defineComponent, ref,} from 'vue'
import {Spin} from 'ant-design-vue'
import {getEl} from "@/util/utils"
import logger from "@/util/logger"

export default defineComponent({
  name: "loading",
  props: {
    show: Boolean
  },
  components: {Spin},
  setup() {
    let show = ref(false)
    let tipMsg = ref(null)
    const showLoad = (msg) => {
      show.value = true
      if (msg) {
        tipMsg.value = msg
      } else {
        tipMsg.value = ''
      }
      // 一级菜单
      let elMain = getEl("container")
      if (elMain) {
        elMain.style.pointerEvents = 'none'
      }
    }

    const hideLoad = () => {
      show.value = false
      setTimeout(() => {
        // 一级菜单
        let elMain = getEl("container")
        if (elMain) {
          elMain.style.pointerEvents = 'auto'
        }
      }, 400)
    }

    return {
      show,
      showLoad,
      hideLoad,
      tipMsg,
    }
  },
})
</script>

<style scoped lang="scss">
#loadingPage {
  background-color: rgba(36, 34, 34, 0.5);
  text-align: center;
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 9999;
  pointer-events: none;
}

.loading {
  pointer-events: none;
}

.spin {
  position: relative;
  top: 50%;
  pointer-events: none !important;
}

</style>

2.创建loading.js

import {createApp} from "vue"
import Loading from '@/components/loading'

export default {
    loading: null,
    install(app, options) {
        if (this.loading) {
            // 防止多次载入
            app.config.globalProperties.$loading = this.loading
            return
        }
        //app.use() 对同一个插件多次调用,该插件只会被安装一次
        let dom = document.body.appendChild(document.createElement("div"))
        this.loading = createApp(Loading,{...options}).mount(dom)
        app.config.globalProperties.$loading = this.loading;
    }
}

3.在main.js中挂载,导入创建的函数,先使用后挂载

import loadConfig from "./util/loading"
app.use(loadConfig)
.mount("#app")

4.界面中使用

const {proxy} = getCurrentInstance()

const getData = ()=>{
  proxy.$loading.showLoad(t("uploading"))
setTimeout(()=>{
 proxy.$loading.hideLoad()
},5000)
}

vue3 + ts 中挂载全局Loading时使用Vue2的方法时会有很多问题 ,应该是不支持这样去做了。使用组件会一劳永逸

问题1:在ts中使用需要声明类型
新建一个 类型文件.d.ts

type Load = {
    showLoad: (msg?: string) => void,
    hideLoad: () => void
}

declare module "@vue/runtime-core" {
    interface ComponentCustomProperties {
        $hideLoad:Function;
        $showLoad:Function;
        $loading: Load
            // Record<string, any> | null | undefined;
    }
}

export {}

如果不添加这个导出 export{} 在其他界面因为追加了类型声明导致在.vue中的界面所有从‘vue’中引入的方法都找不到报错“module vue has no exported member ref”,添加后就好了

问题2:即时导出Loading组件里的方法在外部界面中使用也无法找到; 使用各种姿势我也是找不到啊

install(app: App) {
        const Vnode: VNode = createVNode(GlobalLoading)
        render(Vnode, document.body)
        app.config.globalProperties.$loading = {
            hideLoad: Vnode.component?.exposed?.hideLoad(),
            showLoad: Vnode.component?.exposed?.showLoad(),
        },
        app.config.globalProperties.$hideLoad =  Vnode.component?.exposed?.hideLoad(),
        app.config.globalProperties.$showLoad =  Vnode.component?.exposed?.showLoad()
    }

问题3:
在界面中使用 是这样才不报错,但是找不着啊,不知道为什么

const {proxy} = getCurrentInstance() as ComponentInternalInstance
 proxy?.$loading.hideLoad()  //  找不到实现不了调用不了 

最终通过创建组件引入来调用

loading.vue那个文件还是那个文件
1.创建挂载组件文件,这段参考别人的,地址是找不着了

import {createApp} from "vue";
import Loading1 from "@/library/antds/loading/LoadingCustom.vue";

let loadingInstance;

const LoadingGlobal = {
    showLoad(message?:string) {
        if (!loadingInstance) {
            const loadingApp = createApp(Loading1);
            const mountNode = document.createElement("div");
            document.body.appendChild(mountNode);
            loadingInstance = loadingApp.mount(mountNode);
        }
        loadingInstance.showLoad(message);
    },
    hideLoad() {
        if (loadingInstance) {
            loadingInstance.hideLoad();
        }
    }
};

export default LoadingGlobal;

2.界面中使用

import LoadingGlobal from "@/plugins/loading";

LoadingGlobal.showLoad("收货入库中,请稍等~")

同时需要注意modal点击穿透