vue制作全局loading

最近做项目的时候,发现自定义loading组件,发现网上的loading组件主要有两种情况:

1.是组件开发,这样开发需要在引用的地方都要引入一遍,感觉比较麻烦。

 <template>
     <div class="loading">
       <img width="24" height="24" src="./loading.gif">
       <p class="desc">{{title}}</p>
     </div>
</template>
<script type="text/ecmascript-6">
   export default {
       props: {
           title: {
             type: String,
             default: '正在载入...'
           }
     }
 }
</script>
<style scoped>
 .loading{
   width: 100%;
   text-align: center;
  }
 .desc{
   line-height: 20px;
   font-size: 12px;
   color: white;
 }
</style>

这样每次使用的时候

<template>
 <div class="music-list">
   <loading></loading>
 </div>
</template>
<script type="text/ecmascript-6">
 import Loading from 'base/loading/loading'
 export default {
   components: {
     Loading
   }
 }
</script>

2.是使用install注册组件(Vue.use()来使用)

import './index.css'
 let Loading = {}
// 避免重复install,设立flag
Loading.installed = false
Loading.install = function (Vue) {
 if (Loading.installed) return
 Vue.prototype.$loading = {}
 Vue.prototype.$loading.show = () => {
 // 如果页面有loading则不继续执行
 if (document.querySelector('#vue-loading')) return
 // 1、创建构造器,定义loading模板
 let LoadingTip = Vue.extend({
  template: `<div id="vue-loading">
     <div class="loader"></div>
     </div>`
 })
 // 2、创建实例,挂载到文档以后的地方
 let tpl = new LoadingTip().$mount().$el
 // 3、把创建的实例添加到body中
 document.body.appendChild(tpl)
 // 阻止遮罩滑动
 document.querySelector('#vue-loading').addEventListener('touchmove', function (e) {
  e.stopPropagation()
  e.preventDefault()
 })
 Loading.installed = true
 }
 Vue.prototype.$loading.hide = () => {
 let tpl = document.querySelector('#vue-loading')
 document.body.removeChild(tpl)
 }
}
export default Loading 

将该组件导出,这里就存在一个关键点:install, 只有使用install了,我们在main.js中,才能够直接use该组件,而install函数默认自带一个参数Vue,也就是我们正在使用的Vue对象,然后定义loading这一组件,使用$mount()给组件手动挂载参数,然后将组件插入页面中。

index.css

#vue-loading{
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
}
#vue-loading .loader{}
  position: absolute;
  width: 2.5em;
  height: 2.5em;
  top: calc(50% - 1.25em);
  left: calc(50% - 1.25em);
  transform: rotate(165deg);
}
#vue-loading .loader:before, #vue-loading .loader:after{
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  display: block;
  width: 0.5em;
  height: 0.5em;
  border-radius: 0.25em;
  transform: translate(-50%, -50%);
}
#vue-loading .loader:before{
  animation: before 2s infinite;
}
#vue-loading .loader:after{
  animation: after 2s infinite;
}
.loading-context{
  position: absolute;
  width: 100%;
  top: calc(50% + 2.25em);
  text-align: center;
  height: 30px;
  line-height: 30px;
}
 
 
@keyframes before {
  0% {
    width: 0.5em;
    box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);
  }
  35% {
    width: 2.5em;
    box-shadow: 0 -0.5em rgba(225, 20, 98, 0.75), 0 0.5em rgba(111, 202, 220, 0.75);
  }
  70% {
    width: 0.5em;
    box-shadow: -1em -0.5em rgba(225, 20, 98, 0.75), 1em 0.5em rgba(111, 202, 220, 0.75);
  }
  100% {
    box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);
  }
}
 
@keyframes after {
  0% {
    height: 0.5em;
    box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);
  }
  35% {
    height: 2.5em;
    box-shadow: 0.5em 0 rgba(61, 184, 143, 0.75), -0.5em 0 rgba(233, 169, 32, 0.75);
  }
  70% {
    height: 0.5em;
    box-shadow: 0.5em -1em rgba(61, 184, 143, 0.75), -0.5em 1em rgba(233, 169, 32, 0.75);
  }
  100% {
    box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);
  }
}

使用:

// 在main.js中引入
import loading from "@/base/loading"

// 然后通过 USE方法全局注册
Vue.use(Loading)

// 全局调用
this.$loading.show(options) 
this.$loading.hide(options)

但是这种方法,只能在vue实例存在的页面中使用,比如重新封装ajax,在ajax里添加loading,这个时候往往ajax都是封装在单独的js文件中,此时,vue实例不存在,就无法使用。故在上面的基础上改进如下版本:

import './index.css'
 let installed = false
// 避免重复install,设立flag
const loading =  {
 show(context = '') {
  if (installed) return
 // 如果页面有loading则不继续执行
 if (document.querySelector('#vue-loading')) return
  // 1、创建构造器,定义loading模板
  let divWrapper = document.createElement('div')
  divWrapper.setAttribute("id","vue-loading")
  let div = document.createElement('div')
  div.setAttribute('class','loader')
  let span = document.createElement('span')
  span.className = 'loading-context'
  span.innerHTML = context
  divWrapper.appendChild(div)
  divWrapper.appendChild(span)
  // 3、把创建的实例添加到body中
  document.body.appendChild(divWrapper)
  // 阻止遮罩滑动
  document.querySelector('#vue-loading').addEventListener('touchmove', function (e) {
    e.stopPropagation()
    e.preventDefault()
  })
  installed = true
 },
 hide() {
  let tpl = document.querySelector('#vue-loading')
  if(!tpl) return
  document.body.removeChild(tpl)
 }
}
export default loading

index.css

#vue-loading{
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
}
#vue-loading .loader{}
  position: absolute;
  width: 2.5em;
  height: 2.5em;
  top: calc(50% - 1.25em);
  left: calc(50% - 1.25em);
  transform: rotate(165deg);
}
#vue-loading .loader:before, #vue-loading .loader:after{
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  display: block;
  width: 0.5em;
  height: 0.5em;
  border-radius: 0.25em;
  transform: translate(-50%, -50%);
}
#vue-loading .loader:before{
  animation: before 2s infinite;
}
#vue-loading .loader:after{
  animation: after 2s infinite;
}
.loading-context{
  position: absolute;
  width: 100%;
  top: calc(50% + 2.25em);
  text-align: center;
  height: 30px;
  line-height: 30px;
}
 
 
@keyframes before {
  0% {
    width: 0.5em;
    box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);
  }
  35% {
    width: 2.5em;
    box-shadow: 0 -0.5em rgba(225, 20, 98, 0.75), 0 0.5em rgba(111, 202, 220, 0.75);
  }
  70% {
    width: 0.5em;
    box-shadow: -1em -0.5em rgba(225, 20, 98, 0.75), 1em 0.5em rgba(111, 202, 220, 0.75);
  }
  100% {
    box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);
  }
}
 
@keyframes after {
  0% {
    height: 0.5em;
    box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);
  }
  35% {
    height: 2.5em;
    box-shadow: 0.5em 0 rgba(61, 184, 143, 0.75), -0.5em 0 rgba(233, 169, 32, 0.75);
  }
  70% {
    height: 0.5em;
    box-shadow: 0.5em -1em rgba(61, 184, 143, 0.75), -0.5em 1em rgba(233, 169, 32, 0.75);
  }
  100% {
    box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);
  }
}

使用:

// 在使用的页面中引入
import loading from "@/base/loading"

// 使用
loading.show()
loading.hide()

// 也可以在main.js将组将挂载到vue实例中

Vue.prototype.loading = loading

// 使用
this.$loading.show() 
this.$loading.hide() 

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • 一:什么是闭包?闭包的用处? (1)闭包就是能够读取其他函数内部变量的函数。在本质上,闭包就 是将函数内部和函数外...
    xuguibin阅读 9,557评论 1 52
  • ## 框架和库的区别?> 框架(framework):一套完整的软件设计架构和**解决方案**。> > 库(lib...
    Rui_bdad阅读 2,899评论 1 4
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 2,204评论 0 6
  • 独卧榻前难安眠,大雨滂沱帷幔湿。春风不解兰花意,玉萧万里递情思。
    婼離阅读 274评论 0 4
  • 既然框架能跑起来,接下来当然是分析代码。在My First Spring-Boot Project(1)提到需要添...
    Benson_Lim阅读 153评论 0 0