【问题标题】:Watch doesn't get fire/trigger when global property change全局属性更改时手表不会触发/触发
【发布时间】:2021-01-27 15:08:01
【问题描述】:

我是 Vue 的新手,我从 Vue 3 开始。我试图将模板从 Vue 2 迁移到 Vue 3,以便我可以开始我的项目。

我有这个插件文件。

侧边栏\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 对象。

谁能给我提示我在这里缺少什么?为什么手表不会被解雇。提前致谢。

【问题讨论】:

    标签: vue.js plugins watch vuejs3 vue-reactivity


    【解决方案1】:

    问题是你没有让你的$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>
    

    【讨论】:

    • 感谢@Daniel,解决了这个问题。我正在使用app.config.globalProperties.$sidebar,因为我正在研究所有这些并在 vue3 文档中找到了它。你是对的,最好将存储在另一个文件中。再次感谢?。
    • 很高兴它成功了。附带说明一下,如果您正在构建大型应用程序/项目,我建议您考虑使用 vuex 来管理您的全球商店。
    • 感谢@Daniel 的建议,我将使用 vuex,因为应用程序的未来大小并有利于代码的可追溯性和可维护性。
    猜你喜欢
    • 2023-03-15
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    相关资源
    最近更新 更多