Vuetify3中如何检测NavigationDrawer非激活状态并同步App.vue变量
问题背景
在Vuetify 3中使用NavigationDrawer组件时,需要检测组件是否处于关闭(非激活)状态,从而更新App.vue中的状态变量。此前在Vuetify 2中通过父组件传递prop的方式,能在抽屉关闭时自动同步变量,但当前出现异常:首次点击AppBar的汉堡图标可正常打开抽屉,后续操作却需要双击汉堡图标才能重置传入抽屉的prop变量。目前仅点击汉堡图标时会触发updateNavDrawerHandler函数,需实现该函数在抽屉自身关闭(如点击遮罩、按ESC键)时也能触发。
相关代码文件
AppBar.vue(包含汉堡图标)
<template> <v-app-bar app color='primary' dark> <div class='d-flex app-viewport'> <v-app-bar-nav-icon v-if='user.isLoggedIn && $vuetify.display.smAndDown' @click='updateNavDrawerHandler'> </v-app-bar-nav-icon> </div> </v-app-bar> </template> <script lang='ts'> import { defineComponent, Ref, ref, toRaw, watch } from 'vue'; import { useUserStore } from '@/store/userStore/index'; import { User } from '@/models/domain/user'; export default defineComponent({ name: 'AppBar', emits: ['user-logging-in', 'user-logging-out', 'user-signing-up', 'update-nav-drawer'], setup(props, { emit }) { const userStore = useUserStore(); const user: Ref<User> = ref(userStore.getUser); const updateNavDrawerHandler = (): void => { emit('update-nav-drawer', null, null); }; watch( () => userStore.getUser, () => { user.value = toRaw(userStore.getUser); } ); return { user, updateNavDrawerHandler, }; }, }); </script>
App.vue(状态管理与组件传递)
<template> <v-app> <div class='app-viewport'> <NavigationDrawer :navDrawerStatus='navDrawerStatus' :userLoggedIn='user.isLoggedIn' /> <app-bar v-on:update-nav-drawer='updateNavDrawerHandler' /> <v-main> <router-view /> </v-main> </div> </v-app> </template> <script lang='ts'> import { defineComponent, Ref, ref, toRaw, watch, } from 'vue'; import { useUserStore } from '@/store/userStore/index'; import AppBar from '@/components/navigation/AppBar.vue'; import NavigationDrawer from '@/components/navigation/NavigationDrawer.vue'; import { User } from '@/models/domain/user'; export default defineComponent({ name: 'App', components: { AppBar, NavigationDrawer, }, setup() { // Initialize stores const userStore = useUserStore(); // Navbar functionality const navDrawerStatus: Ref<boolean> = ref(false); const updateNavDrawerHandler = (): void => { navDrawerStatus.value = !navDrawerStatus.value; }; // User set up const user: Ref<User> = ref( toRaw(userStore.getUser) ); watch( () => userStore.getUser, () => { user.value = toRaw(userStore.getUser); } ); return { user, navDrawerStatus, updateNavDrawerHandler, }; }, }); </script>
NavigationDrawer.vue(抽屉组件)
<template> <v-navigation-drawer app color='secondary' :model-value='navDrawerStatus' v-if='userLoggedIn'> </v-navigation-drawer> </template> <script lang='ts'> import { defineComponent } from 'vue'; export default defineComponent({ name: 'NavigationDrawer', props: { navDrawerStatus: { type: Boolean, default: false }, userLoggedIn: { type: Boolean, default: false }, }, }); </script>
解决方案
问题核心是抽屉的状态变更未同步回父组件。Vuetify 3的v-navigation-drawer通过model-value控制状态,但当前仅实现了单向传递,未监听抽屉自身的关闭事件。
步骤1:改造NavigationDrawer实现双向绑定
修改抽屉组件,监听update:model-value事件并向父组件同步状态:
<template> <v-navigation-drawer app color='secondary' :model-value='navDrawerStatus' @update:model-value="handleDrawerUpdate" v-if='userLoggedIn' > </v-navigation-drawer> </template> <script lang='ts'> import { defineComponent } from 'vue'; export default defineComponent({ name: 'NavigationDrawer', props: { navDrawerStatus: { type: Boolean, default: false }, userLoggedIn: { type: Boolean, default: false }, }, emits: ['update:navDrawerStatus'], setup(props, { emit }) { const handleDrawerUpdate = (newValue: boolean) => { emit('update:navDrawerStatus', newValue); }; return { handleDrawerUpdate }; } }); </script>
步骤2:在App.vue中同步状态
使用Vue的双向绑定语法糖,或手动监听事件同步navDrawerStatus:
<template> <v-app> <div class='app-viewport'> <!-- 方式1:使用v-model语法糖 --> <NavigationDrawer v-model:navDrawerStatus='navDrawerStatus' :userLoggedIn='user.isLoggedIn' /> <!-- 方式2:手动监听事件(等效于v-model) --> <!-- <NavigationDrawer :navDrawerStatus='navDrawerStatus' @update:navDrawerStatus="navDrawerStatus = $event" :userLoggedIn='user.isLoggedIn' /> --> <app-bar v-on:update-nav-drawer='updateNavDrawerHandler' /> <v-main> <router-view /> </v-main> </div> </v-app> </template>
效果验证
改造完成后,无论点击汉堡图标切换状态,还是通过抽屉自身的关闭逻辑(遮罩、ESC键)关闭抽屉,navDrawerStatus都会自动同步,无需双击汉堡图标即可正常切换状态。
内容的提问来源于stack exchange,提问作者Joe King
相关产品推荐
相关产品推荐

