vue lottie 自定义loading指令
做什么梦呢 人气:0一、前言
本文主要介绍使用lottie动画实现vue自定义loading的指令方法。另外本篇文章还会介绍其他几个常用的自定义指令实现方式(点击指定区域外监听指令)。
lottie是一款由airbnb开源的跨平台动画渲染库,支持Android
,iOS
,Web
,Windows
平台。是专门用于解析从AE(Adobe After Effects)中通过Bodymovin
插件导出的JSON文件,直接渲染动画。
二、实现方式
1.v-loading
这个指令是我们在开发过程中经常遇到的场景,这里我们分两步做,第一步我们先创建一个loading的组件。
这里我们要先引入lottie
插件
npm install lottie-web // or yarn add lottie-web
之后在loading组件中引入
// loading.vue <template> <div class="loading-wrap"> <div id="loadingImg" /> </div> </template> <script> import lottie from "lottie-web" // 在网上下载的lottie动画,这里我是在iconfont上找的 import animationData from "./loading.json" export default { mounted() { // 解决json动画找不到dom不渲染问题 window.requestAnimationFrame(this.loadImg); }, methods: { loadImg () { lottie.loadAnimation({ container: document.getElementById('loadingImg'), renderer: "svg", loop: true, autoplay: true, animationData: animationData }); } } }; </script> <style lang="less" scoped> .loading-wrap { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background-color: #fff; display: flex; align-items: center; justify-content: center; z-index: 1800; } </style>
然后去在创建一个js文件去写指令
import Vue from 'vue' import Loading from './loading.vue' /** * Vue.extend 接受参数并返回一个构造器,new 该构造器可以返回一个组件实例 * 当我们 new Mask() 的时候,把该组件实例挂载到一个 div 上 **/ const Mask = Vue.extend(Loading) // 更新是否显示 const toggleLoading = (el, binding) => { if (binding.value) { Vue.nextTick(() => { // 获取父元素的定位信息 const isStatic = window.getComputedStyle(el).position === 'static' if (isStatic) { el.style.position = 'relative' } // 插入到目标元素 insertDom(el, el, binding) }) } else { removeDom(el, el, binding) } } // 插入到目标元素 const insertDom = (parent, el) => { parent.appendChild(el.mask) } // 从目标元素中移除 const removeDom = (parent, el) => { parent.removeChild(el.mask) } export default { // 第一次绑定到元素时调用 bind: function (el, binding) { const mask = new Mask({ el: document.createElement('div') }) // 用一个变量接住mask实例 el.instance = mask el.mask = mask.$el el.maskStyle = {} binding.value && toggleLoading(el, binding) }, // 所在组件的 VNode 更新时调用--比较更新前后的值 update: function (el, binding) { if (binding.oldValue !== binding.value) { toggleLoading(el, binding) } }, // 指令与元素解绑时调用 unbind: function (el) { el.instance && el.instance.$destroy() } }
然后我们再去main.js中,全局注册一下
import Directive from './directives' Vue.use(Directive)
最后,在使用的时候,就可以这样
// App.vue <template> <div id="app" v-loading="isLoading"> </div> </template> <script> export default { name: 'App', data () { return { isLoading: true } }, mounted () { setTimeout(() => { this.isLoading = false }, 3000) } } </script>
以上 我们就封装好了一个lottie的自定义loading。
2.v-click-outside
这个指令是点击目标区域以外的地方的监听。在日常开发中,我们可能会遇到自定义的一些弹窗效果,这个时候,这个指令就派上用场了。
// clickoutside.js export default { bind (el, binding, vnode) { function documentHandler (e) { if (el.contains(e.target)) { return false } if (binding.expression) { binding.value(e) } } el.__vueClickOutside__ = documentHandler document.addEventListener('click', documentHandler) }, update () { }, unbind (el, binding) { document.removeEventListener('click', el.__vueClickOutside__) delete el.__vueClickOutside__ } }
之后是使用方法, 如下
<template> <div id="app"> <img v-click-outside="handleOutSide" src="./assets/logo.png" > </div> </template> <script> export default { name: 'App', methods: { handleOutSide () { console.log('到外面了') } } } </script>
最后记得在index.js中将两个指令定义一下,再去main.js中注册到全局。
import Loading from './loading' import clickoutside from './clickoutside' export default { install (Vue) { Vue.directive('loading', Loading), Vue.directive('click-outside', clickoutside) } }
目录结构如图
以上我们就实现了常用指令的自定义。
三、后记
关于自定义指令有非常多,比如权限时候可能会用到、占位图、loading等。我们都可以用指令的封装,快速便捷的实现一些功能。
加载全部内容