当全局 属性 更改时,Watch 不会得到 fire/trigger

Watch doesn't get fire/trigger when global property change

我是 Vue 的新手,我从 Vue 3 开始。我试图将一个模板从 Vue 2 迁移到 Vue 3,这样我就可以开始我的项目了。

我有这个插件文件。

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

我还有一个 BaseTopNavLay 布局文件,因此我可以使用 handleSidebarToggle onclick 按钮方法

切换侧边栏
<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>

这里是 App.vue 文件中的 watch

<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>

无论我在哪里测试 var this.$sidebar.showSidebar,我都可以正确访问它的值。此外,onclick 方法正在更改 Sidebar\Index.ts 插件文件中的 SidebarStore 对象。

任何人都可以提示我我在这里缺少什么吗?为什么手表不被解雇。提前致谢。

问题是你没有让你的 $sidebar 反应,watch 需要使用反应变量。

你可以把商店保留在你拥有的地方,但我会把它放在一个单独的文件中 (store.js) 并在需要的地方导入,不需要把它放在 app.config.globalProperties.$sidebar 上(但是这可能是个人喜好

// store.js
// using reactive (all values)
export const SidebarStore = Vue.reactive({
    showSidebar: false,
    sidebarLinks: [],
})
// or using ref (one for each)
// export const showSidebar = Vue.ref(false);

export const displaySidebar = (value: boolean) => {
    SidebarStore.showSidebar.value = value;
}

这将使 SidebarStoredisplaySidebar 在您的代码中的任何地方都可用

这样使用

<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'
    import { SidebarStore, displaySidebar } from '../store'

   
    export default defineComponent({
        name: 'BaseTopNavLay',
        components: {
            ModalComp
        },
        // ...
        methods: {
            handleSidebarToggle (): void {
                displaySidebar(!SidebarStore.showSidebar)
            },
            handleHideSideBar (): void {
                displaySidebar(false)
            },
        }
    })
</script>