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 thelottie-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-lottie
的vue
组件里引入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
,执行一下操作
-
首先我们要引入自己写好的组件
import { createApp } from "vue" //引入写好的loading组件 import Loading from './src/a-loading.vue';
-
挂载我们的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) }
-
编写自定义指令并导出
// 创建自定义指令 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
-
总代码如下:
//引入写好的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
-
全局注册自定义指令
在
main.js
中import aLoading from "./components/a-loading/index.js" createApp(App).directive("aloading", aLoading).mount("#app")
-
使用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了,想实现你们具体操作就看大家去扩展优化啦!!!!