Vue

by WILLIAM CORREA

HTML

<div id="app">
  <button @click="showLoading">Loading</button>
  <vue-loading inline-template>
    <div
      v-if="loading"
      class="loading"
      @click="$loading(false)"
    >
      <div class="lds-ring">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
      </div>
    </div>
  </vue-loading>
</div>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

.loading {
  position: absolute;
  background: rgba(0, 0, 0, 0.6);
  height: 100vh;
  width: 100vw;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lds-ring {
  display: inline-block;
  position: relative;
  width: 64px;
  height: 64px;
}

.lds-ring div {
  box-sizing: border-box;
  display: block;
  position: absolute;
  width: 51px;
  height: 51px;
  margin: 6px;
  border: 6px solid #fff;
  border-radius: 50%;
  animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
  border-color: #fff transparent transparent transparent;
}

.lds-ring div:nth-child(1) {
  animation-delay: -0.45s;
}

.lds-ring div:nth-child(2) {
  animation-delay: -0.3s;
}

.lds-ring div:nth-child(3) {
  animation-delay: -0.15s;
}

@keyframes lds-ring {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

Vue

Vue.component('vue-loading', {
	data: () => ({
  	loading: false
  }),
  methods: {
  	show () {
    	this.loading = true
    },
  	hide () {
    	this.loading = false
    }
  },
  created () {
		this.$root.$on('loading:show', this.show)
    this.$root.$on('loading:hide', this.hide)
  },
  beforeDestroy () {
		this.$root.$off('loading:show')
    this.$root.$off('loading:hide')
  }
})

Vue.prototype.$loading = function (loading = true) {
  if (loading) {
  	this.$root.$emit('loading:show')
    return
  }
  this.$root.$emit('loading:hide')
}

new Vue({
  el: "#app",
  methods: {
  	showLoading () {
    	this.$loading()
    }
  }
})