I’m very new to Vue and I begin with Vue 3. I was trying to migrate a template from Vue 2 to Vue 3 so I can start with my project.
I have this plugin file.
Sidebar\Index.ts
import SidebarPlugComp from './SidebarPlugComp.vue'
import SidebarLinkPlugComp from './SidebarLinkPlugComp.vue'
// tiny internal plugin store
const SidebarStore = {
showSidebar: false,
sidebarLinks: [],
displaySidebar (value: boolean) {
this.showSidebar = value
}
}
const SidebarPlugin = {
install (app: any) {
app.config.globalProperties.$sidebar = SidebarStore
app.component('side-bar-plug-comp', SidebarPlugComp)
app.component('sidebar-link-plug-comp', SidebarLinkPlugComp)
}
}
export default SidebarPlugin
Also I have a BaseTopNavLay layout file so I can toggle the sidebar with handleSidebarToggle onclick button method
<template>
\\...
<div class="navbar-toggle d-inline" :class="{toggled: $sidebar.showSidebar}">
<button type="button"
class="navbar-toggler"
aria-label="Navbar toggle button"
@click.prevent="handleSidebarToggle">
<span class="navbar-toggler-bar bar1"></span>
<span class="navbar-toggler-bar bar2"></span>
<span class="navbar-toggler-bar bar3"></span>
</button>
\\ ...
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { ModalComp } from '../components'
export default defineComponent({
name: 'BaseTopNavLay',
components: {
ModalComp
},
// ...
methods: {
handleSidebarToggle (): void {
this.$sidebar.displaySidebar(!this.$sidebar.showSidebar)
},
handleHideSideBar (): void {
this.$sidebar.displaySidebar(false)
},
}
})
</script>
And here is the watch in the App.vue file
<template>
<component :is="this.$route.meta.layout || 'div'">
<router-view />
</component>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'Application',
methods: {
toggleNavOpen () {
console.log('here')
let root = document.getElementsByTagName('html')[0]
root.classList.toggle('nav-open')
}
},
/*watch: {
'$sidebar.showSidebar': function(newVal, oldVal) {
console.log(newVal, oldVal)
}
}*/
mounted () {
//@ts-ignore
this.$watch('$sidebar.showSidebar', this.toggleNavOpen)
}
})
</script>
Wherever I test the var this.$sidebar.showSidebar
I can access to its value properly. Also, the onclick method is changing the SidebarStore
object in Sidebar\Index.ts plugin file.
Can anyone give me a hint what am I missing here? Why the watch doesn't get fired. Thanks in advance.
The problem is that you have not made your
$sidebar
reactive, and awatch
needs to use a reactive variable.You can keep the store where you have it, but I'd put it into a separate file (store.js) and import where needed, no need to put it on
app.config.globalProperties.$sidebar
(but that might be a personal preferencethis will make
SidebarStore
anddisplaySidebar
available anywhere in your codeuse like this