I am new to Vue and have a component A) Notification bar which has a Reactive object containing state, message. Then I want to show a div in another component based on the status of Reactive object in component A. Also I want to be able to change the Reactive object in component A from a method in component B. How do you achieve this?
Component A:
<template>
<div v-html="$notificationStore.message" v-if="$notificationStore.notify"></div>
</template>
<script setup>
import { reactive } from "vue";
const $notificationStore = reactive({
notify: false,
type: "",
message: ""
});
</script>
Component B:
<template>
<div v-if="!$notificationStore.notify"></div> <!-- Should read "notify" from Component A"-->
<button type="button" @click="ShowNotification('Message to show')"/>
</template>
<script setup>
import { reactive } from "vue";
function ShowNotification(message){
this.$notificationStore.notify = true;
this.$notificationStore.Message = message;
};
</script>
Thank you very much!
You don't need to use $
for your data properties.
Be sure that you understand the security risks bound with using v-html
directive
There are better ways to achieve the same result, without using v-html
.
UPDATE
I have changed the example to cover using SFCs.
You can pass your store to your components through props.
<comp-a :store="myStore"></comp-a>
Pay attention, that props are readonly. Since we pass an reactive object, you still can change the object properties from the component but this is a bad practice and is not recommended.
It is recommended to keep any mutations to reactive state inside of the provider whenever possible.
I would also suggest you to try using Pinia instead of developing your own custom store solution.
const { createApp, reactive } = Vue;
const myStore = reactive({
notify: false,
type: "",
message: "",
showNotification: function(message) {
this.notify = true;
this.message = message;
}
})
const CompA = {
props: ['store'],
template: 'CompA: <div v-html="store.message" v-if="store.notify"></div>'
}
const CompB = {
props: ['store'],
template: `CompB:
<div v-if="!store.notify">
<button type="button" @click="store.showNotification('Message from CompB')">show</button>
</div>`
}
const App = {
components: { CompA, CompB },
setup() {
return { myStore }
}
}
const app = createApp(App)
app.mount('#app')
#app { line-height: 1.75; }
[v-cloak] { display: none; }
<div id="app">
<comp-a :store="myStore"></comp-a><br/>
<comp-b :store="myStore"></comp-b>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>