头图

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的,命令如下:

npm install vue3-lottie@latest --save

如图所示:

2. 使用vue3-lottie

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

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

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

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

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

    <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组件里面输入以下代码

<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. 首先我们要引入自己写好的组件

    import { createApp } from "vue"
    //引入写好的loading组件
    import Loading  from './src/a-loading.vue';
  1. 挂载我们的loading组件

    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)
    }
  1. 编写自定义指令并导出

    // 创建自定义指令
    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
  1. 总代码如下:

    //引入写好的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
  1. 全局注册自定义指令

    main.js

    import aLoading from "./components/a-loading/index.js"
    
    createApp(App).directive("aloading", aLoading).mount("#app")
  1. 使用aLoading指令

    <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了,想实现你们具体操作就看大家去扩展优化啦!!!!


一柯白菜
16 声望0 粉丝

坚持,热爱