vue2 & [vue3 ts]全局loading挂载

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点击穿透

Vue3中使用TypeScript结合Pinia来实现全局loading的方式如下: 首先,我们需要安装vue-router、pinia和axios,可以使用以下命令进行安装: ``` npm install vue-router@next pinia axios ``` 接下来我们创建一个store模块来管理全局loading状态。在src/store目录下创建一个名为loading.ts的文件,代码如下: ```typescript import { store } from 'pinia'; export const useLoadingStore = store('loading'); export const loadingStore = useLoadingStore({ state: () => ({ isLoading: false, }), actions: { setLoading(loading: boolean) { this.isLoading = loading; }, }, }); ``` 然后在src/main.ts文件中注册pinia和创建一个全局loading插件,代码如下: ```typescript import { createApp } from 'vue'; import { createPinia } from 'pinia'; import App from './App.vue'; import router from './router'; import axios from 'axios'; import { loadingStore } from './store/loading'; const app = createApp(App); const pinia = createPinia(); app.use(pinia); // 创建全局loading插件 app.config.globalProperties.$loading = { show() { loadingStore.setLoading(true); }, hide() { loadingStore.setLoading(false); }, }; // axios拦截器 axios.interceptors.request.use(function (config) { loadingStore.setLoading(true); return config; }, function (error) { return Promise.reject(error); }); axios.interceptors.response.use(function (response) { loadingStore.setLoading(false); return response; }, function (error) { loadingStore.setLoading(false); return Promise.reject(error); }); app.use(router); app.mount('#app'); ``` 最后,在需要使用loading的地方,可以通过以下方式来调用全局loading状态: ```typescript import { defineComponent } from 'vue'; import { loadingStore } from './store/loading'; export default defineComponent({ methods: { fetchData() { loadingStore.setLoading(true); // 发起异步请求 // ... loadingStore.setLoading(false); }, }, }); ``` 以上就是使用Vue3和TypeScript结合Pinia实现全局loading的方法。我们首先在store模块中定义了一个loading状态,并提供了相应的方法来控制loading的显示和隐藏。然后在main.ts中创建了全局loading插件,并通过axios的拦截器来控制loading的显示和隐藏。最后,在需要使用loading的地方调用相应的方法即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值