lottie+vue3自定义指令封装一个v-loading

lottie+vue3自定义指令封装一个v-loading

用过ui组件库的朋友们都v-loading是让指定元素出现加载图或者文字,来提示用户这块数据正在加载中,而这些组件库的v-loading都是固定的转圈图标居多,我们现实的开发中可能还使用一些动态来加载

这时候那些组件库的加载组件就不适用了,我们就需要去自定义自己的加载组件,而定义加载组件的时候我们可以选择用动态图片来自定义,但是图片或者gif来做自定义指令的话性能是比不上本期主题的lottie,那么就让我们进入正题来介绍该库和怎么使用该库开自定义我们的v-loading

1.什么是lottie

Lottie是Airbnb发布的一款开源动画库,它适用于Android、iOS、Web和Windows的库。Lottie是通过AE设计好动画效果,通过bodymovin插件直接导出json文件,让开发直接调用,让开发使用Lottie库就可以实现动画效果了,大大节约了开发成本,提升工作效率。

用我们通俗易懂的话来说就是只有我们提供一个JSON格式的动图文件,通过lottie就可以把它以动图形式显示在我们的界面上。

2. Lottie的优势

  • 动画设计是由专业的动画制作工具After Effects来制作的,使动画更加的简便和效果更好
  • 支持跨平台,开发成本低,一套Lottie动画可以在Android/IOS/Web多端使用
  • 使用lottie方案,json文件大小会比gif文件或png 序列文件小很多,性能也会更好。
  • lottie提供 具有较丰富全面的控制方法和事件监听的支持

3.Lottie的下载与使用

在这里的话项目是vue3的,所以我们用vue3的版本的Lottie,但是这里提个醒,只要vue3版本才可以这样用,不是vue3版本去Lottie官网或者自己找教程,废话少说,我们直接进入正题。

1. 安装vue3-lottie

vue3-lottie was created to help developers add Lottie animations to their Vue 3 applications. In my search for a simple way to add Lottie animations to my Vue application I found a suprising lack of maintained solutions. vue3-lottie is a vue wrapper around the lottie-web library with a few additional features.

用我的理解vue3-lottie是为了将Lottie动画添加到Vue3应用程序,推出的一种可维护性解决方案,同时还增加了一些额外的功能。那么这里的下载是用npm的,命令如下:

powershell 复制代码
npm install vue3-lottie@latest --save

如图所示:

2. 使用vue3-lottie

在上面我们说到lottie是解析json形成动画的,所以我们要去下载一个JSON格式的动画。这里推荐一个下载可以被lottie解析的JSON网站lottiefiles,下载好之后把他复制到我们项目的assets/json文件夹下

  • 在我们需要用到vue3-lottievue组件里引入vue3-lottie

    vue 复制代码
    <script setup>
    import Vue3Lottie from "vue3-liott";
    </script>
  • 然后引入我们刚刚下载好的JSON文件的

    vue 复制代码
    <script setup>
    import Vue3Lottie from "vue3-liott"
    import sandClock from "@/assets/json/sandClock"
    </script>
  • 然后在template使用我们的Vue3Lottie组件

    这里就介绍三个属性,其他的大家去vue3-lottie了解

    vue 复制代码
    <script setup>
    import {Vue3Lottie} from "vue3-liott"
    import sandClock from "@/assets/json/sandClock"
    </script>
    
    <template>
    	<!-- width:宽度,height:高度,animationData:加载的json文件 -->
    	<Vue3Lottie width="200px" height="200px" :animationData="sandClock" />
    </template>
    
    <style scoped></style>
  • 运行项目查看效果如下:

4.利用vue的自定义指令加vue3-liotte封装v-loading

1.利用vue3-liotte编写Loading

我们在components文件夹新建一个a-loading文件夹,在里面的src文件夹下面新建一个a-loading.vue组件

然后在a-loading.vue组件里面输入以下代码

vue 复制代码
<template>
  <div>
    <Vue3Lottie :animationData="sandClock"  :height="42" :width="30"/>
    <div class="text">正在努力查询中...</div>
  </div>
</template>

<script setup>
import { Vue3Lottie } from 'vue3-lottie' // 详细介绍https://www.npmjs.com/package/vue3-lottie
import sandClock from "@/assets/json/sandClock.json"
</script>

<style lang="scss" scoped>

</style>

2.编写自定义loading指令

我们在我们a-loading文件夹下面新建一个index.js,执行一下操作

  1. 首先我们要引入自己写好的组件

    javascript 复制代码
    import { createApp } from "vue"
    //引入写好的loading组件
    import Loading  from './src/a-loading.vue';
  2. 挂载我们的loading组件

    javascript 复制代码
    function createLoading(el){
      // 创建div标签
      const loadingDom = document.createElement('div')
      // 添加自定义属性作为标识,避免重复loading
      loadingDom.setAttribute('data-v','loading')
      // 设置样式,父元素相对定位,子元素绝对定位父元素之上
      el.style.position = 'relative'
      loadingDom.style.width = `${el.offsetWidth}px`
      loadingDom.style.height = `${el.offsetHeight}px`
      loadingDom.style.maxHeight = '100vh'
      loadingDom.style.position = `absolute`
      loadingDom.style.background = `#fff`
      loadingDom.style.display = `flex`
      loadingDom.style.justifyContent = `center`
      loadingDom.style.alignItems = `center`
      loadingDom.style.top = '0'
     
    
      loadingDom.style.borderRadius = 'inherit'
      // 创建APP实例,传入loading组件,并且挂载loading组件和创建的标签
      const app = createApp(Loading)
      const instance = app.mount(loadingDom)
      loadingDom.appendChild(instance.$el)
      el.appendChild(loadingDom)
    }
  3. 编写自定义指令并导出

    javascript 复制代码
    // 创建自定义指令
    const aLoading = {
      //mounted的时候,v-loading变量值为true时,加载loading
      mounted(el,binding) {
        if(binding.value === true){
          createLoading(el)
        }
      },
      //update的时候
      updated(el,binding){
        //v-loading 的值为false,并且该节点下最后一个元素是loading时,移除节点
        if(binding.value === false && el.lastChild.dataset.v === 'loading'){
          el.removeChild(el.lastChild)
          return
        }
        //v-loading 的值为true,并且该节点下没有loading节点时,调用函数,挂载loading
        if(binding.value === true && el.lastChild.dataset.v !== 'loading'){
          createLoading(el)
        }
      }
    }
     
    //导出创建好的指令
    export default aLoading
  4. 总代码如下:

    javascript 复制代码
    //引入写好的loading组件
    import Loading  from './src/a-loading.vue';
    
    function createLoading(el){
      // 创建div标签
      const loadingDom = document.createElement('div')
      // 添加自定义属性作为标识,避免重复loading
      loadingDom.setAttribute('data-v','loading')
      // 设置样式,父元素相对定位,子元素绝对定位父元素之上
      el.style.position = 'relative'
      loadingDom.style.width = `${el.offsetWidth}px`
      loadingDom.style.height = `${el.offsetHeight}px`
      loadingDom.style.maxHeight = '100vh'
      loadingDom.style.position = `absolute`
      loadingDom.style.background = `#fff`
      loadingDom.style.display = `flex`
      loadingDom.style.justifyContent = `center`
      loadingDom.style.alignItems = `center`
      loadingDom.style.top = '0'
     
    
      loadingDom.style.borderRadius = 'inherit'
      // 创建APP实例,传入loading组件,并且挂载loading组件和创建的标签
      const app = createApp(Loading)
      const instance = app.mount(loadingDom)
      loadingDom.appendChild(instance.$el)
      el.appendChild(loadingDom)
    }
    
    // 创建自定义指令
    const aLoading = {
      //mounted的时候,v-loading变量值为true时,加载loading
      mounted(el,binding) {
        if(binding.value === true){
          createLoading(el)
        }
      },
      //update的时候
      updated(el,binding){
        //v-loading 的值为false,并且该节点下最后一个元素是loading时,移除节点
        if(binding.value === false && el.lastChild.dataset.v === 'loading'){
          el.removeChild(el.lastChild)
          return
        }
        //v-loading 的值为true,并且该节点下没有loading节点时,调用函数,挂载loading
        if(binding.value === true && el.lastChild.dataset.v !== 'loading'){
          createLoading(el)
        }
      }
    }
     
    //导出创建好的指令
    export default aLoading
  5. 全局注册自定义指令

    main.js

    javascript 复制代码
    import aLoading from "./components/a-loading/index.js"
    
    createApp(App).directive("aloading", aLoading).mount("#app")
  6. 使用aLoading指令

    vue 复制代码
    <script setup>
    import { ref } from "vue"
    let loading = ref(false)
    const handelLoading = () => {
    	loading.value = true
    	setTimeout(() => {
    		loading.value = false
    	}, 3000)
    }
    </script>
    
    <template>
    	<button @click="handelLoading">点我加载</button>
    	<div class="hh" v-aloading="loading"></div>
    </template>
    
    <style scoped>
    .hh {
    	width: 600px;
    	height: 600px;
    	background-color: red;
    }
    </style>

    运行代码点击按钮如下图所示:

我们就成功了

到这里我们就实现了一个简单的loading了,想实现你们具体操作就看大家去扩展优化啦!!!!

相关推荐
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅7 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端
爱敲代码的小鱼8 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
吹牛不交税8 小时前
admin.net-v2 框架使用笔记-netcore8.0/10.0版
vue.js·.netcore