vue自定义loading

全屏loading效果

在这里插入图片描述

div v-loading loading效果

在这里插入图片描述

测试

<template>
  <div>
    <div v-loading="isLoading" style="width: 300px;height: 300px;">
      loading
    </div>
    <button @click="loading">loading</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      isLoading: false
    };
  },
  created () { },
  computed: {},
  mounted () { },
  methods: {
    loading () {
      // this.$fullScreenLoading.open();
      // setTimeout(() => {
      //   this.$fullScreenLoading.close();
      // }, 3000);

      this.isLoading = true
      // setTimeout(() => {
      //   this.isLoading = false
      // }, 2000);

    },

  }
};
</script>
<style scoped>
/* @import url(); 引入css类 */
</style>

指令方式

loading.css

// loading.css
.load-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 9999;
  background-color: rgba(220, 220, 224, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
} 
.loader {
  font-size: 20px;
  margin: 5em auto;
  width: 1em;
  height: 1em;
  border-radius: 50%;
  position: relative;
  text-indent: -9999em;
  -webkit-animation: load-animation 1.3s infinite linear;
  animation: load-animation 1.3s infinite linear;
}
@-webkit-keyframes load-animation {
  0%,
  100% {
    box-shadow: 0em -3em 0em 0.2em #1c28d3, 2em -2em 0 0em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 -0.5em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 0em #1c28d3;
  }
  12.5% {
    box-shadow: 0em -3em 0em 0em #1c28d3, 2em -2em 0 0.2em #1c28d3, 3em 0em 0 0em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 -0.5em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  25% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 0em #1c28d3, 3em 0em 0 0.2em #1c28d3, 2em 2em 0 0em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 -0.5em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  37.5% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 0em #1c28d3, 2em 2em 0 0.2em #1c28d3, 0em 3em 0 0em #1c28d3, -2em 2em 0 -0.5em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  50% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 0em #1c28d3, 0em 3em 0 0.2em #1c28d3, -2em 2em 0 0em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  62.5% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 0em #1c28d3, -2em 2em 0 0.2em #1c28d3, -3em 0em 0 0em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  75% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 0em #1c28d3, -3em 0em 0 0.2em #1c28d3, -2em -2em 0 0em #1c28d3;
  }
  87.5% {
    box-shadow: 0em -3em 0em 0em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 0em #1c28d3, -3em 0em 0 0em #1c28d3, -2em -2em 0 0.2em #1c28d3;
  }
}
@keyframes load-animation {
  0%,
  100% {
    box-shadow: 0em -3em 0em 0.2em #1c28d3, 2em -2em 0 0em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 -0.5em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 0em #1c28d3;
  }
  12.5% {
    box-shadow: 0em -3em 0em 0em #1c28d3, 2em -2em 0 0.2em #1c28d3, 3em 0em 0 0em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 -0.5em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  25% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 0em #1c28d3, 3em 0em 0 0.2em #1c28d3, 2em 2em 0 0em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 -0.5em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  37.5% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 0em #1c28d3, 2em 2em 0 0.2em #1c28d3, 0em 3em 0 0em #1c28d3, -2em 2em 0 -0.5em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  50% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 0em #1c28d3, 0em 3em 0 0.2em #1c28d3, -2em 2em 0 0em #1c28d3, -3em 0em 0 -0.5em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  62.5% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 0em #1c28d3, -2em 2em 0 0.2em #1c28d3, -3em 0em 0 0em #1c28d3, -2em -2em 0 -0.5em #1c28d3;
  }
  75% {
    box-shadow: 0em -3em 0em -0.5em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 0em #1c28d3, -3em 0em 0 0.2em #1c28d3, -2em -2em 0 0em #1c28d3;
  }
  87.5% {
    box-shadow: 0em -3em 0em 0em #1c28d3, 2em -2em 0 -0.5em #1c28d3, 3em 0em 0 -0.5em #1c28d3, 2em 2em 0 -0.5em #1c28d3, 0em 3em 0 -0.5em #1c28d3, -2em 2em 0 0em #1c28d3, -3em 0em 0 0em #1c28d3, -2em -2em 0 0.2em #1c28d3;
  }
}

Loading.vue

<template>
  <div v-show="visible" class="load-container">
    <div class="loader"></div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      visible: false
    };
  },
  created () { },
  computed: {},
  mounted () { },
  methods: {}
};
</script>
<style scoped>
/* @import url(); 引入css类 */
@import url(./loading.css);
</style>

loading/index.js

import Vue from 'vue'
import Loading from './Loading'

const LoadingComponent = Vue.extend(Loading)

const toggleLoading = (el, binding) => {
  if (binding.value) {
    Vue.nextTick(() => {
      // 控制loading组件显示
      el.instance.visible = true
      // 插入到目标元素
      insertElement(el, el, binding)
    })
  } else {
    el.instance.visible = false
  }
}

const insertElement = (parent, el) => {
  // 给父元素加个定位,让loading元素定位
  el.style.position = 'relative';
  parent.appendChild(el.loadingComponent)
}

export default {
  /**
   * 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
   * @param {*} el 
   * @param {*} binding 
   * @param {*} vnode 
   */
  bind: function (el, binding, vnode) {
    const loadingComponent = new LoadingComponent({
      el: document.createElement('div'),
      data () { }
    })
    el.instance = loadingComponent
    el.loadingComponent = loadingComponent.$el
    el.loadingComponentStyle = {}
    binding.value && toggleLoading(el, binding)
  },
  update: function (el, binding) {
    if (binding.oldValue !== binding.value) {
      toggleLoading(el, binding)
    }
  },
  /**
   * 只调用一次,指令与元素解绑时调用。
   * @param {*} el 
   * @param {*} binding 
   */
  unbind: function (el, binding) {
    el.style.position = '';
    el.instance && el.instance.$destroy()
  }
}

directives/index.js

import loading from './loading';
export default {
  install (Vue) {
    // 全局loading
    Vue.directive("loading", loading)
  }
}

引入指令

//引入插件
import Loading from './directives '
Vue.use(Loading);

插件方式

plugins/loading.js


import Loading from './Loading'

export default {
  install (Vue) {

    const LoadingComponent = Vue.extend(Loading)

    const toggleLoading = (el, binding) => {
      if (binding.value) {
        Vue.nextTick(() => {
          // 控制loading组件显示
          el.instance.visible = true
          // 插入到目标元素
          insertElement(el, el, binding)
        })
      } else {
        el.instance.visible = false
      }
    }

    const insertElement = (parent, el) => {
      // 给父元素加个定位,让loading元素定位
      el.style.position = 'relative';
      parent.appendChild(el.loadingComponent)
    }
    //添加指令
    Vue.directive('loading', {
      /**
       * 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
       * @param {*} el 
       * @param {*} binding 
       * @param {*} vnode 
       */
      bind: function (el, binding, vnode) {
        const loadingComponent = new LoadingComponent({
          el: document.createElement('div'),
          data () { }
        })
        el.instance = loadingComponent
        el.loadingComponent = loadingComponent.$el
        el.loadingComponentStyle = {}
        binding.value && toggleLoading(el, binding)
      },
      update: function (el, binding) {
        if (binding.oldValue !== binding.value) {
          toggleLoading(el, binding)
        }
      },
      /**
       * 只调用一次,指令与元素解绑时调用。
       * @param {*} el 
       * @param {*} binding 
       */
      unbind: function (el, binding) {
        el.style.position = '';
        el.instance && el.instance.$destroy()
      }

    })
  }
}

引入插件

//引入插件
import Loading from './plugins/loading.js '
Vue.use(Loading );

全屏loading

/**
 * 自定义FullScreenLoading
 */
const FullScreenLoading = {
  show: false,
  component: null
}

export default {
  install (Vue) {
    Vue.prototype.$fullScreenLoading = function (text = '正在加载中...', type) {
      if (type === 'close') {
        FullScreenLoading.component.show = FullScreenLoading.show = false;
      } else {
        if (FullScreenLoading.show) {
          return
        }
        /**
         * Vue构造器,创建一个“子类”,参数是一个包含组件选项的对象,其中,data选项中必须是函数
         * Vue.extend通常和Vue.extend + $mount()
         */
        let FullScreenLoadingComponent = Vue.extend({
          data: function () {
            return {
              show: FullScreenLoading.show
            }
          },
          template: `<div class="fullScreenLoading-container" v-show="show"><div  class="fullScreenLoading">${text}</div></div>`
        })
        FullScreenLoading.component = new FullScreenLoadingComponent()
        let element = FullScreenLoading.component.$mount().$el
        document.body.appendChild(element)
        FullScreenLoading.component.show = FullScreenLoading.show = true
      }
    };
    // 添加实例方法
    ['open', 'close'].forEach(type => {
      Vue.prototype.$fullScreenLoading[type] = (text) => Vue.prototype.$fullScreenLoading(text, type);
    });

  }
}

引入全屏插件

//引入插件
import './plugins/fullScreenLoading.css'
import fullScreenLoading from './plugins/fullScreenLoading'
Vue.use(fullScreenLoading);
  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值