Vue 3 - parent/child load mask
by skirtle
HTML
<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<div id="app">
<div v-for="i in 3" :key="i">
<label><input type="radio" v-model="id" :value="i"> {{ i }}</label>
</div>
<child-component :id="id"></child-component>
<div class="load-mask" v-show="$loading.isLoading.value"></div>
</div>
CSS
.load-mask {
background: #ccc;
bottom: 0;
left: 0;
opacity: 0.4;
position: fixed;
right: 0;
top: 0;
z-index: 100;
}
JavaScript
const ChildComponent = {
props: ['id'],
template: `
<div>
{{ id }}
<template v-if="$loading.isLoading.value">
- Loading
</template>
<button @click="loadData">Reload</button>
</div>
`,
methods: {
loadData () {
this.$loading.start()
// Pretend HTTP request
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.$loading.stop()
}, 2000)
}
},
watch: {
id: {
flush: 'pre',
handler () {
this.loadData()
}
}
}
}
const app = Vue.createApp({
components: {
ChildComponent
},
data () {
return {
id: 1
}
}
})
app.config.globalProperties.$loading = {
isLoading: Vue.ref(false),
start () {
this.isLoading.value = true
},
stop () {
this.isLoading.value = false
}
}
app.mount('#app')