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

Vue JS侧边导航下拉列表路由切换后无法自动关闭的解决方案

Vue侧边导航路由切换时自动关闭下拉菜单的解决方案

问题描述

  • 带下拉列表的Vue侧边导航,从下拉列表内的路由(如news/contact)切换到独立路由(如home/about)时,下拉列表始终保持展开状态,仅页面刷新后才会关闭。
  • 尝试给<router-view/>添加:key="$route.fullPath"强制重新渲染组件,但导致下拉列表无法正常展开。

提供的侧边导航代码

<template>
    <nav class="navbar-default navbar-static-side" role="navigation" >
        <div class="sidebar-collapse">
            <ul class="nav metismenu" id="side-menu">
                <li class="nav-header">
                    <div class="dropdown profile-element">
                            <a data-toggle="dropdown" class="dropdown-toggle" >
                            <span class="clear"> <span class="block m-t-xs"> <strong class="font-bold">David Williams</strong>
                             </span> <span class="text-muted text-xs block">Art Director <b class="caret"></b></span> </span> </a>
                            <ul class="dropdown-menu animated fadeInRight m-t-xs">
                                <li><a href="#">Logout</a></li>
                            </ul>
                    </div>
                    <div class="logo-element">
                        IN+
                    </div>
                </li>
                <li :class="{ 'active': $route.name === 'home' }">
                    <router-link :to="{ name: 'home' }">
                        <i class="fa fa-home"></i>
                        <span>Home</span>
                    </router-link>
                </li>
                
                <li :class="{ 'active': $route.name === 'about' }">
                    <router-link :to="{ name: 'about' }">
                        <i class="fa fa-book"></i>
                        <span>About</span>
                    </router-link>
                </li>

                <li :class="{ 'active': $route.name === 'news' || $route.name === 'contact'}">
                    <a ><i class="fa fa-bar-chart-o"></i> <span class="nav-label">Others</span><span class="fa arrow"></span></a>
                    <ul class="nav nav-second-level collapse">
                    <li :class="{ 'active': $route.name === 'news' }">
                        <router-link :to="{ name: 'news' }">
                            <span>News</span>
                        </router-link>
                    </li>
                    <li :class="{ 'active': $route.name === 'contact' }">
                        <router-link :to="{ name: 'contact' }">
                            <span>Contact</span>
                        </router-link>
                    </li>
                    </ul>
                </li>
            </ul>

        </div>
    </nav>
</template>

<script>
export default {
    name : "SideNav",
}
</script>

<style>

</style>

原因分析

原代码使用了MetisMenu插件(通过metismenu类标识),该插件依赖jQuery操作DOM来控制菜单展开收起。给<router-view/>添加:key="$route.fullPath"会强制每次路由变化都重新渲染页面组件,导致MetisMenu的初始化状态丢失,从而无法正常展开下拉菜单。

解决方案

方案一:用Vue响应式状态控制菜单(推荐,摆脱jQuery依赖)

通过Vue的响应式数据和路由监听,手动控制下拉菜单的展开/收起:

  1. 修改组件的<script>部分,添加状态管理和路由监听:
export default {
    name : "SideNav",
    data() {
        return {
            // 控制Others下拉菜单的展开状态
            othersMenuOpen: false
        }
    },
    watch: {
        // 监听路由变化,自动调整菜单状态
        $route(to) {
            if (['news', 'contact'].includes(to.name)) {
                this.othersMenuOpen = true;
            } else {
                this.othersMenuOpen = false;
            }
        }
    },
    mounted() {
        // 初始化时根据当前路由设置菜单状态
        this.othersMenuOpen = ['news', 'contact'].includes(this.$route.name);
    }
}
  1. 修改模板中的下拉菜单部分,绑定状态到DOM类:
  • 给触发下拉的<a>标签添加点击事件:
<a @click="othersMenuOpen = !othersMenuOpen">
    <i class="fa fa-bar-chart-o"></i> 
    <span class="nav-label">Others</span>
    <span class="fa arrow"></span>
</a>
  • 修改二级菜单的collapse类绑定:
<ul class="nav nav-second-level" :class="{ 'collapse': !othersMenuOpen }">

方案二:保留MetisMenu,路由变化时重置菜单

如果需要继续使用MetisMenu插件,可在路由变化时重新初始化菜单:

  1. 修改组件的<script>部分:
export default {
    name : "SideNav",
    mounted() {
        // 初始化MetisMenu
        this.$nextTick(() => {
            $('#side-menu').metisMenu();
        });
    },
    watch: {
        $route() {
            this.$nextTick(() => {
                // 销毁旧实例并重新初始化,或直接关闭展开的菜单
                $('#side-menu').metisMenu('dispose');
                $('#side-menu').metisMenu();
                // 也可直接关闭所有展开的菜单:$('.metismenu .collapse.in').collapse('hide');
            });
        }
    }
}

说明

方案一更符合Vue的响应式思想,避免了对jQuery和DOM操作的依赖,也不会出现组件重新渲染导致的状态丢失问题。

内容的提问来源于stack exchange,提问作者Isaac Hatilima

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 16:39:44