You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vuetify3中如何检测NavigationDrawer非激活状态并同步App.vue变量

Vuetify 3中检测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>
<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 20:14:54