The correct way of doing this in Vue is to communicate between components, in this case it might not be a simple parent/child communication, so you might want to create an Event Bus.
By using this approach the modal's code is has minimum effects on the rest of your application, it only dispatches events that you can subscribe to from any other component.
Note: In this case you won't add the class on your body tag (because you can't mount Vue on body), but you may just add it to your root div to have a similar result.
const eventBus = new Vue();
Vue.component('modal', {
props: ['isOpen'],
template: `
<div class="modal" v-if="isOpen">This is a modal</div>
`,
});
Vue.component('wrapper', {
template: `
<div>
<modal :isOpen="isModalOpen"></modal>
<button @click="toggleModal">toggle modal</button>
</div>
`,
data() {
return {
isModalOpen: false,
}
},
methods: {
toggleModal() {
this.isModalOpen = !this.isModalOpen;
eventBus.$emit('toggleModal', this.isModalOpen);
}
}
});
new Vue({
el: "#app",
data: {
active: false,
},
created() {
eventBus.$on('toggleModal', (isModalOpen) => {
this.active = isModalOpen;
});
},
})
.active {
background: grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app" :class="{active}">
<wrapper></wrapper>
</div>