I want to make a "Loader" component, I want it to be fully independent and already working just by being included in the layout. but to be able to use it I need to expose some methods
So I arrived at the following code:
<script setup>
let active = false;
function show() {
active = true;
}
function hide() {
active = false;
}
window.loader = {show, hide};
</script>
<template>
<Transition name="loader">
<div v-if="active">
</div>
</Transition>
</template>
<style scoped>
/* All styles and transitions */
.loader {
position: fixed;
height: 100vh;
width: 100vw;
background: #000;
z-index: 9999;
top: 0;
left: 0;
opacity: 0.5;
}
</style>
however the show and hide methods do not change the internal state of the component
I want to use it like this: BaseLayout.vue
<template>
<div >
<Loader />
<slot>All application body</slot>
</div>
</template>
Is there any way to expose these functions globally and change the internal state of the loader component?
Is there a pattern I can use to solve this problem?
I use this loader in several different layouts and I would like to use as little code as possible to insert in a new layout
CodePudding user response:
You can do something like :
<script setup>
import {ref} from 'vue'
let active = ref(false);
function show() {
active.value = true;
}
function hide() {
active.value = false;
}
window.loader = {show, hide, active};
</script>
<template>
<Transition name="loader">
<div v-if="active">
</div>
</Transition>
</template>
<style scoped>
/* All styles and transitions */
.loader {
position: fixed;
height: 100vh;
width: 100vw;
background: #000;
z-index: 9999;
top: 0;
left: 0;
opacity: 0.5;
}
</style>
it will allow vue to detect changes correctly
CodePudding user response:
Define a composable function with ref
property outside the function in order to be global, and use that methods to change its state :
useLoader.js
import {ref} from 'vue';
const active = false;
export default useLoader(){
function show() {
active.value = true;
}
function hide() {
active.value = false;
}
return {active,hide,show}
}
in the loader component :
<script setup>
import useLoader from './useLoader'
const {active} =useLoader();
</script>
<template>
<Transition name="loader">
<div v-if="active">
</div>
</Transition>
</template>
in other component :
<script setup>
import useLoader from './useLoader'
const {show,hide} =useLoader();
</script>
<template>
<div >
<button @click="show">show loader</button>
<Loader />
<slot>All application body</slot>
</div>
</template>