vue3 使用封装loading

vue2请看这篇文章 vue2封装loading

  • 自己写一个loading页面,用作单个div的loading
  1. 在components中创建一个名为loading.vue的组件
<template>
  <transition name="fade">
    <section>
      <div class="loading">
        <img class="icon-animation" src="@/assets/loading.png" />
        <p class="desc">数据加载中...</p>
      </div>
    </section>
  </transition>
</template>
<script>
  export default {
    
    computed: {
    },
    data () {
      return {
       
      }
    },
    methods: {
      
    },
    destroyed() {
    },
    mounted() {

      
    }
  }
</script>
<style scoped lang="scss">
  @-ms-keyframes iconRotate {
    0% {
      -ms-transform: rotate(0deg);
    }

    25% {
      -ms-transform: rotate(90deg);
    }

    50% {
      -ms-transform: rotate(180deg);
    }

    75% {
      -ms-transform: rotate(270deg);
    }

    100% {
      -ms-transform: rotate(360deg);
    }
  }
  @keyframes iconRotate {
    0% {
      -webkit-transform: rotate(0deg);
    }

    25% {
      -webkit-transform: rotate(90deg);
    }

    50% {
      -webkit-transform: rotate(180deg);
    }

    75% {
      -webkit-transform: rotate(270deg);
    }

    100% {
      -webkit-transform: rotate(360deg);
    }
  }
  .fade-enter-active,
  .fade-leave-active {
    transition: opacity 0.5s;
  }
  .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
    opacity: 0;
  }
  section {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    background: transparent;
    z-index: 99;
    .loading {
      width: 100%;
      text-align: center;
      /* flex-direction: column; */
    }
    .icon-animation {
      width: 60px;
      height: 60px;
      animation: iconRotate 1s linear infinite;
    }
    .desc {
      font-size: 14px;
      color: rgb(95, 89, 89);
    }
  }
</style>

  1. 在utils文件下创建一个名为loading的文件夹,文件夹下创建一个名为index.js和loading.js的文件
  • loading.js
import { createApp, nextTick } from 'vue';
import Loading from '@/components/loading';

// 创建Loading组件实例
const Mask = createApp(Loading);
const maskInstance = Mask.mount(document.createElement('div'));

// 更新是否显示
const toggleLoading = (el, binding) => {
   if (binding.value) {
       nextTick(() => {
           // 控制loading组件显示
           el.instance.visible = true;
           el.style.position = 'relative';
           // 插入到目标元素
           insertDom(el, el);
       });
   } else {
       el.instance.visible = false;
       el.style.position = 'static';
       el.mask && el.mask.parentNode && el.mask.parentNode.removeChild(el.mask);
   }
};

// 插入到目标元素
const insertDom = (parent, el) => {
   parent.appendChild(el.mask);
};

export default {
   // 第一次绑定到元素时调用
   mounted(el, binding) {
       // 用一个变量接住mask实例
       el.instance = maskInstance;
       el.mask = maskInstance.$el;
       el.maskStyle = {};
       binding.value && toggleLoading(el, binding);
   },
   // 所在组件的 VNode 更新时调用--比较更新前后的值
   updated(el, binding) {
       if (binding.oldValue !== binding.value) {
           toggleLoading(el, binding);
       }
   },
   // 指令与元素解绑时调用
   unmounted(el) {
       el.instance = null;
       el.mask = null;
       el.maskStyle = null;
   },
};
  • index.js
/**在Vue 3中,全局指令的注册需要使用app.directive方法,
 * 而不再需要在Vue上直接调用。在install方法中,
 * app参数代表Vue应用的实例,通过调用app.directive来注册全局指令。
 * 另外,由于Vue 3的模块化系统改变,导入Vue的方式也有所不同,
 * 不再需要import Vue from 'vue',
 * 而是直接传递Vue应用的实例作为参数。 */
import Loading from './loading'

export default {
    install(app) {
        app.directive('myLoading', Loading)
    }
}
  1. 在main.js中引用
import DirectiveLoading from '@/utils/loading'
const app = createApp(App)
app.use(DirectiveLoading)
  1. 在页面使用
<template>
  <div v-myLoading="loading"></div>
</template>
<script>
  export default {
    data() {
      return {
        loading: false
      }
    }
  }
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3中,我们可以使用`provide`和`inject`来实现全局loading封装。首先,在根组件中创建一个loading组件: ```vue <template> <div v-if="loading" class="loading-mask"> <div class="loading-spinner"></div> </div> <slot></slot> </template> <script> export default { data() { return { loading: false } }, methods: { show() { this.loading = true }, hide() { this.loading = false } } } </script> <style> .loading-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.7); display: flex; align-items: center; justify-content: center; z-index: 9999; } .loading-spinner { width: 40px; height: 40px; border: 3px solid #fff; border-top-color: #888; border-radius: 50%; animation: loading-spinner 0.8s linear infinite; } @keyframes loading-spinner { to { transform: rotate(360deg); } } </style> ``` 然后,在根组件中提供`loading`实例: ```vue <template> <loading v-slot="{ show, hide }"></loading> <router-view></router-view> </template> <script> import Loading from '@/components/Loading.vue' export default { provide: { loading: new Loading() } } </script> ``` 接下来,在需要使用loading组件使用`inject`注入`loading`实例,然后调用`show()`和`hide()`方法即可: ```vue <template> <div> <button @click="getData">加载数据</button> </div> </template> <script> export default { inject: ['loading'], methods: { async getData() { try { this.loading.show() // 请求数据 } catch (e) { console.error(e) } finally { this.loading.hide() } } } } </script> ``` 这样,我们就实现了一个简单的全局loading组件封装

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值