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

Vuetify实现嵌套菜单时列表项无法点击问题排查

Vuetify嵌套菜单点击无响应问题排查

我正参考Vuetify嵌套菜单实现示例为个人Vuetify项目开发嵌套菜单功能,我的实现代码如下:

<template>
<v-container>
    <v-app>
        <v-app-bar app>
            <v-toolbar-title>Schnitzeljagd</v-toolbar-title>
            <!-- OLD CODE -->
            <v-menu :close-on-content-click="false" open-on-hover bottom offset-y>
                <template v-slot:activator="{ on }">
                    <v-btn icon v-on="on">
                        <v-icon>mdi-dots-vertical</v-icon>
                    </v-btn>
                </template>

                <v-list>
                    <v-list-item>
                        <v-list>
                            <select v-model="locale">
                                <option v-for="lang in locales" :key="lang.code" :value="lang.code">{{
                                        lang.name
                                }}
                                </option>
                            </select>
                        </v-list>
                    </v-list-item>

                    <v-list-group v-model="active" no-action>
                        <template v-slot:activator>
                            <v-list-tile>
                                <v-list-tile-content>
                                    <v-list-tile-title>Language</v-list-tile-title>
                                </v-list-tile-content>
                            </v-list-tile>
                        </template>
                        <select>
                            <option v-for="lang in locales" :key="lang.code">
                                   {{ lang.name }}
                            </option>
                        </select>
            <!-- NEW CODE -->


                    </v-list-group>
                </v-list>
            </v-menu>
            <v-menu left bottom>


                <v-list>
                    <v-list-item>
                        <LanguageSwitcher />
                    </v-list-item>
                    <v-list-item>
                        <v-list color="deep-purple accent-4" dense dark>
                            <select v-model="locale">
                                <option v-for="lang in locales" :key="lang.code" :value="lang.code">{{
                                        lang.name
                                }}
                                </option>
                            </select>
                        </v-list>
                    </v-list-item>
                </v-list>
            </v-menu>
        </v-app-bar>

    </v-app>
</v-container>
</template>
<script>
export default {
    data: () => ({
      locales: [
            { name: 'English' },
            { title: 'Italian' },
          ]
    }),
    components: {}
}
</script>

如代码所示,我将代码分为标注为「OLD CODE」的旧代码块与「NEW CODE」的新代码块:旧代码生成的菜单样式效果不佳,因此我调整编写了新代码,期望实现和参考示例一致的样式效果,但运行时发现新代码内的列表项无法正常响应点击操作。


问题原因

新代码的点击失效是多个问题叠加导致的:

  • 第二个v-menu缺失必填的activator触发器插槽,没有绑定触发元素和对应的事件,菜单本身的交互逻辑就不完整
  • 第二个v-menu没有配置:close-on-content-click="false",默认点击内容区域就会直接关闭菜单,视觉上就和点击没反应一样
  • 响应式变量定义不全:v-model绑定的locale、v-list-group绑定的active都没有在data中初始声明,Vue无法追踪这些值的变化,交互不会触发视图更新
  • locales数组字段不统一:英语项用的是name字段,意大利语项错写为title,循环渲染时部分选项拿不到文本,绑定的code字段完全缺失,key和value都取不到有效值
  • 混用了Vuetify废弃组件和原生控件:v-list-tile是Vuetify 1.x版本的组件,2.x以上版本已经废弃替换为v-list-item,组件不兼容会导致事件绑定失效;原生select的事件冒泡会被Vuetify菜单的遮罩层拦截,无法正常触发选择操作
  • 引用的LanguageSwitcher组件没有在components选项中注册,组件渲染失败也会阻塞区域内的交互事件

修复方案

直接替换为以下可运行代码即可:

<template>
<v-container>
    <v-app>
        <v-app-bar app>
            <v-toolbar-title>Schnitzeljagd</v-toolbar-title>
            <!-- 修复后的嵌套菜单 -->
            <v-menu :close-on-content-click="false" bottom offset-y>
                <template v-slot:activator="{ on, attrs }">
                    <v-btn icon v-bind="attrs" v-on="on">
                        <v-icon>mdi-dots-vertical</v-icon>
                    </v-btn>
                </template>

                <v-list>
                    <v-list-group v-model="languageMenuOpen" no-action>
                        <template v-slot:activator>
                            <v-list-item>
                                <v-list-item-content>
                                    <v-list-item-title>Language</v-list-item-title>
                                </v-list-item-content>
                            </v-list-item>
                        </template>
                        <v-list-item 
                            v-for="lang in locales" 
                            :key="lang.code" 
                            @click="locale = lang.code"
                        >
                            <v-list-item-title>{{ lang.name }}</v-list-item-title>
                        </v-list-item>
                    </v-list-group>
                </v-list>
            </v-menu>
        </v-app-bar>
    </v-app>
</v-container>
</template>

<script>
export default {
    data: () => ({
      // 补全所有响应式变量初始值
      locale: 'en',
      languageMenuOpen: false,
      // 统一数组字段结构
      locales: [
            { code: 'en', name: 'English' },
            { code: 'it', name: 'Italian' },
          ]
    }),
    // 注册用到的自定义组件
    components: {
      // LanguageSwitcher  // 引入后在这里注册
    }
}
</script>

关键调整点

  • 移除冗余的第二个v-menu,所有菜单逻辑统一在一个组件内实现,给菜单补全activator插槽,绑定触发事件和属性
  • 给菜单加:close-on-content-click="false"配置,避免点击子项时菜单直接关闭
  • 补全所有data里的响应式变量,统一locales的字段结构,补上唯一标识code
  • 替换废弃的v-list-tile组件为当前版本支持的v-list-item,移除冲突的原生select,直接用Vuetify自带的列表项渲染选项,绑定点击事件切换语言
  • 自定义组件必须在components选项中注册后再使用,避免渲染失败

内容的提问来源于stack exchange,提问作者Tricker Macedonia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:00:59