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
相关产品推荐
相关产品推荐

