当全局 属性 更改时,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;
}
这将使 SidebarStore
和 displaySidebar
在您的代码中的任何地方都可用
这样使用
<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>
我是 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;
}
这将使 SidebarStore
和 displaySidebar
在您的代码中的任何地方都可用
这样使用
<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>