vue3 实现全屏 loading 加载动画

博客包含Loading.vue和index.js代码,结合标签推测与CSS动画相关,涉及CSS3技术,在前端开发中可用于实现动画效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
Loading.vue

<template>
  <div class="loading-wrap">
    <div v-if="mask" class="mask"></div>
    <div class="loading" v-cloak>
      <div class="load-cont">
        <div class="line"></div>
        <div class="line"></div>
        <div class="line"></div>
        <div class="line"></div>
        <div class="line"></div>
        <div class="line"></div>
      </div>
      <div class="text">{{ title || "加载中..." }}</div>
    </div>
  </div>
</template>

<script setup>
defineProps({
  title: {
    type: String
  },
  mask: {
    type: Boolean
  }
})
</script>
<style lang="less" scoped>
.loading-wrap {
  .mask {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    z-index: 3001;
  }

  .loading {
    width: 250px;
    height: 250px;
    position: fixed;
    left: 50%;
    top: 30%;
    background-color: rgba(0, 0, 0, 0.7);
    transform: translateX(-100px);
    border-radius: 10px;
    z-index: 3000;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    .load-cont {
      width: 60px;
      height: 60px;
      position: relative;

      .line {
        position: absolute;
        left: 50%;
        top: 0;
        width: 4px;
        height: 100%;
      }

      .line::before {
        position: absolute;
        top: 0;
        display: block;
        content: '';
        width: 4px;
        height: 15px;
        background-color: white;
        border-radius: 5px 5px 0 0;
      }

      .line::after {
        position: absolute;
        bottom: 0;
        display: block;
        content: '';
        width: 4px;
        height: 15px;
        background-color: white;
        border-radius: 0 0 5px 5px;
      }

      .line:nth-child(2) {
        transform: rotate(30deg);
      }

      .line:nth-child(3) {
        transform: rotate(60deg);
      }

      .line:nth-child(4) {
        transform: rotate(90deg);
      }

      .line:nth-child(5) {
        transform: rotate(120deg);
      }

      .line:nth-child(6) {
        transform: rotate(150deg);
      }

      .line:nth-child(1)::before {
        animation: loading 1.2s linear 0s infinite;
      }

      .line:nth-child(2)::before {
        animation: loading 1.2s linear 0.1s infinite;
      }

      .line:nth-child(3)::before {
        animation: loading 1.2s linear 0.2s infinite;
      }

      .line:nth-child(4)::before {
        animation: loading 1.2s linear 0.3s infinite;
      }

      .line:nth-child(5)::before {
        animation: loading 1.2s linear 0.4s infinite;
      }

      .line:nth-child(6)::before {
        animation: loading 1.2s linear 0.5s infinite;
      }

      .line:nth-child(1)::after {
        animation: loading 1.2s linear 0.6s infinite;
      }

      .line:nth-child(2)::after {
        animation: loading 1.2s linear 0.7s infinite;
      }

      .line:nth-child(3)::after {
        animation: loading 1.2s linear 0.8s infinite;
      }

      .line:nth-child(4)::after {
        animation: loading 1.2s linear 0.9s infinite;
      }

      .line:nth-child(5)::after {
        animation: loading 1.2s linear 1.0s infinite;
      }

      .line:nth-child(6)::after {
        animation: loading 1.2s linear 1.1s infinite;
      }

      @keyframes loading {
        from {
          opacity: 0;
        }

        to {
          opacity: 1;
        }
      }
    }

    .text {
      margin-top: 26px;
      font-size: 30px;
      color: #fff;
    }

  }

}
</style>

index.js

import { createApp } from 'vue'
import Loading from './Loading.vue'

export default {
  instance: null,
  parent: document.createElement('div'),
  showLoading ({ title = '', mask = false }) {
    if (this.instance !== null) this.clear()
    this.instance = createApp(Loading, { title, mask })
    document.body.appendChild(this.parent)
    this.instance.mount(this.parent)
  },
  hideLoading () {
    this.clear()
  },
  clear () {
    if (this.instance !== null) {
      this.instance.unmount(this.parent)
      document.body.removeChild(this.parent)
      this.instance = null
    }
  }, 
}
//调用
import utils from './index.js'
utils.showLoading({title:"loading",mask:true})
### Vue3实现初始化时的全屏加载动画Vue3 项目中,可以通过组合式 API 或选项式 API 来实现初始化时的全屏加载动画。以下是具体的实现方法: #### 1. 创建全局 Loading 组件 可以创建一个独立的 `Loading` 组件用于显示加载动画。此组件可以在应用启动时自动挂载。 ```vue <template> <div v-if="isLoading" class="loading-overlay"> <div class="spinner"></div> </div> </template> <script> import { ref, onMounted, onUnmounted } from &#39;vue&#39;; export default { setup() { const isLoading = ref(true); // 模拟异步数据加载完成后隐藏加载动画 setTimeout(() => { isLoading.value = false; }, 2000); // 延迟两秒模拟加载时间 return { isLoading }; }, }; </script> <style scoped> .loading-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.8); display: flex; justify-content: center; align-items: center; z-index: 9999; } .spinner { border: 4px solid #f3f3f3; /* Light grey */ border-top: 4px solid #3498db; /* Blue */ border-radius: 50%; width: 50px; height: 50px; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } </style> ``` 上述代码定义了一个简单的旋转加载动画,并通过 `setTimeout` 模拟了延迟关闭的效果[^1]。 #### 2. 将 Loading 组件嵌入 App.vue 为了使加载动画在整个应用程序范围内生效,可以直接将其嵌套到根组件 `App.vue` 中。 ```vue <template> <div id="app"> <!-- 加载动画 --> <Loading /> <!-- 应用主体 --> <router-view></router-view> </div> </template> <script> import Loading from &#39;./components/Loading.vue&#39;; export default { components: { Loading }, }; </script> ``` 这样,当应用首次加载时,`Loading` 组件会立即呈现并覆盖整个屏幕,直到其内部逻辑决定停止展示为止。 #### 3. 结合 Vuex 或 Pinia 进行动态控制(可选) 如果希望更灵活地管理加载状态,可以引入状态管理工具如 Vuex 或 Pinia。例如,在 Pinia 中设置一个共享的状态变量来控制加载行为。 ```javascript // store/loading.js import { defineStore } from &#39;pinia&#39;; export const useLoadingStore = defineStore(&#39;loading&#39;, { state: () => ({ isLoading: true, }), actions: { finishLoading() { this.isLoading = false; }, }, }); ``` 随后修改 `Loading.vue` 使用该 Store 控制可见性: ```javascript import { computed } from &#39;vue&#39;; import { useLoadingStore } from &#39;@/store/loading&#39;; export default { setup() { const loadingStore = useLoadingStore(); const isLoading = computed(() => loadingStore.isLoading); setTimeout(() => { loadingStore.finishLoading(); // 调用 action 完成加载 }, 2000); return { isLoading }; }, }; ``` 这种设计允许其他模块显式通知何时结束加载过程[^2]。 --- #### 性能优化建议 - **懒加载资源**:对于非必要的静态文件或第三方库,考虑按需加载以减少初始包大小。 - **骨架屏替代方案**:除了传统的圆形进度条外,还可以采用占位符形式的内容预览作为过渡效果,提升用户体验感知速度[^3]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值