Vue 服务式Loading组件
components 下 loading 下 Loading.vue
<template>
<transition name="fade">
<div class="loading_container" v-show="visible">
<div class="loading_wrapper">
<div class="sk-folding-cube">
<div class="sk-cube1 sk-cube"></div>
<div class="sk-cube2 sk-cube"></div>
<div class="sk-cube4 sk-cube"></div>
<div class="sk-cube3 sk-cube"></div>
</div>
<div class="loading_title">{{ title }}</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: 'Loading',
data() {
return {
visible: false
}
},
props: {
title: {
type: String,
default: 'loading'
}
},
watch: {
visible(val) {
document.body.style.overflow = val ? 'hidden' : null
}
}
}
</script>
<style scoped lang="scss">
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity .6s ease;
}
@keyframes sk-foldCubeAngle {
0%, 10% {
transform: perspective(140px) rotateX(-180deg);
opacity: 0;
}
25%, 75% {
transform: perspective(140px) rotateX(0deg);
opacity: 1;
}
90%, 100% {
transform: perspective(140px) rotateY(180deg);
opacity: 0;
}
}
.loading_container {
position: fixed;
z-index: 1000;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
pointer-events: none;
.loading_wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 120px;
height: 120px;
background-color: rgba(0, 0, 0, .8);
border-radius: 6px;
}
.loading_title {
overflow: hidden;
width: 100%;
box-sizing: border-box;
padding: 0 10px;
font-size: 14px;
line-height: 2em;
color: #fff;
text-align: center;
white-space: nowrap;
text-overflow: ellipsis;
}
.sk-folding-cube {
width: 24%;
height: 24%;
margin: 16px 0;
position: relative;
transform: rotateZ(45deg);
.sk-cube {
float: left;
width: 50%;
height: 50%;
position: relative;
transform: scale(1.1);
&:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
animation: sk-foldCubeAngle 2.4s infinite linear both;
transform-origin: 100% 100%;
background-color: #fff;
}
}
.sk-cube2 {
transform: scale(1.1) rotateZ(90deg);
&:before {
animation-delay: .3s;
}
}
.sk-cube3 {
transform: scale(1.1) rotateZ(180deg);
&:before {
animation-delay: .6s;
}
}
.sk-cube4 {
transform: scale(1.1) rotateZ(270deg);
&:before {
animation-delay: .9s;
}
}
}
}
</style>
components 下 loading 下 index.js
import LoadingComponent from './Loading'
let loadingInstance = null // 单例
const Loading = {
install(Vue) {
Vue.prototype.$loading = {
show(title = 'loading') {
if (!loadingInstance) {
const LoadingConstructor = Vue.extend(LoadingComponent)
loadingInstance = new LoadingConstructor({
props: {
title: {
type: String,
default: title
}
}
}).$mount() // 调用$mount 得到真实dom
document.body.appendChild(loadingInstance.$el)
}
if (!loadingInstance.visible) loadingInstance.visible = true
},
hide() {
if (loadingInstance?.visible) loadingInstance.visible = false
}
}
}
}
export default Loading
main.js
impotarnt Loading form './components/loading'
Vue.use(Loading)
demo
// 组件中
showLoading() {
this.$loading.show('加载中...')
setTimeout(() => {
this.$loading.hide()
}, 2000)
}
为之则易,不为则难。