VUE菜单有一个BUG,当我们点击其它按钮或者首页的时候,已经展示的一级菜单是不会自动收缩的。这个问题也导致很多开发者把一级菜单都换成了二级菜单。
错误的效果请看下图。
因为我使用的是ruoyi的前端框架,所以菜单文件的路径是src/layout/components/Sidebar/index.vue文件,如果大家使用的是其他的框架或者自己写的去全局搜索关键字【el-menu】就能找到菜单页面。文件路径如下图
- // el-menu菜单中添加ref和open事件
- <el-menu ref="menu" @open="handleOpen">el-menu>
- data() {
- return {
- // 记录用户上次点击的菜单索引
- keyIndex:0,
- };
- },
- watch: {
- $route () {
- // 监控用户点击的菜单,如果是首页或者个人详情页面都要把上次打开的页面收缩起来。
- if (this.$route.path === '/index' ||this.$route.path === "/user/profile") {
- this.$refs.menu.close(this.keyIndex);
- }
- }
- },
- methods: {
- handleOpen (key) {
- this.keyIndex = key;
- }
- },
-
- <template>
- <div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
- <logo v-if="showLogo" :collapse="isCollapse" />
- <el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
- <el-menu
- ref="menu"
- @open="handleOpen"
- :default-active="activeMenu"
- :collapse="isCollapse"
- :background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
- :text-color="settings.sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor"
- :unique-opened="true"
- :active-text-color="settings.theme"
- :collapse-transition="false"
- mode="vertical"
- >
- <sidebar-item
- v-for="(route, index) in sidebarRouters"
- :key="route.path + index"
- :item="route"
- :base-path="route.path"
- />
- el-menu>
- el-scrollbar>
- div>
- template>
-
- <script>
- import { mapGetters, mapState } from "vuex";
- import Logo from "./Logo";
- import SidebarItem from "./SidebarItem";
- import variables from "@/assets/styles/variables.scss";
-
- export default {
- components: { SidebarItem, Logo },
- data() {
- return {
- keyIndex:0,
- };
- },
- watch: {
- $route () {
- if (this.$route.path === '/index' ||this.$route.path === "/user/profile") {
- this.$refs.menu.close(this.keyIndex);
- }
- }
- },
- methods: {
- handleOpen (key) {
- this.keyIndex = key;
- }
- },
- computed: {
- ...mapState(["settings"]),
- ...mapGetters(["sidebarRouters", "sidebar"]),
- activeMenu() {
- const route = this.$route;
- const { meta, path } = route;
- // if set path, the sidebar will highlight the path you set
- if (meta.activeMenu) {
- return meta.activeMenu;
- }
- return path;
- },
- showLogo() {
- return this.$store.state.settings.sidebarLogo;
- },
- variables() {
- return variables;
- },
- isCollapse() {
- return !this.sidebar.opened;
- }
- }
- };
- script>
-----华丽的分割线,以下是凑字数,大家不用花时间看,快去改代码-----
-----华丽的分割线,以下是凑字数,大家不用花时间看,快去改代码-----
-----华丽的分割线,以下是凑字数,大家不用花时间看,快去改代码-----
- <template>
- <div v-if="!item.hidden">
- <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
- <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
- <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
- <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="$t(onlyOneChild.meta.title)" />
- el-menu-item>
- app-link>
- template>
-
- <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
- <template slot="title">
- <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
- template>
- <sidebar-item
- v-for="child in item.children"
- :key="child.path"
- :is-nest="true"
- :item="child"
- :base-path="resolvePath(child.path)"
- class="nest-menu"
- />
- el-submenu>
- div>
- template>
-
- <script>
- import path from 'path'
- import { isExternal } from '@/utils/validate'
- import Item from './Item'
- import AppLink from './Link'
- import FixiOSBug from './FixiOSBug'
-
- export default {
- name: 'SidebarItem',
- components: { Item, AppLink },
- mixins: [FixiOSBug],
- props: {
- // route object
- item: {
- type: Object,
- required: true
- },
- isNest: {
- type: Boolean,
- default: false
- },
- basePath: {
- type: String,
- default: ''
- }
- },
- data() {
- this.onlyOneChild = null
- return {}
- },
- methods: {
- hasOneShowingChild(children = [], parent) {
- if (!children) {
- children = [];
- }
- const showingChildren = children.filter(item => {
- if (item.hidden) {
- return false
- } else {
- // Temp set(will be used if only has one showing child)
- this.onlyOneChild = item
- return true
- }
- })
-
- // When there is only one child router, the child router is displayed by default
- if (showingChildren.length === 1) {
- return true
- }
-
- // Show parent if there are no child router to display
- if (showingChildren.length === 0) {
- this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
- return true
- }
-
- return false
- },
- resolvePath(routePath, routeQuery) {
- if (isExternal(routePath)) {
- return routePath
- }
- if (isExternal(this.basePath)) {
- return this.basePath
- }
- if (routeQuery) {
- let query = JSON.parse(routeQuery);
- return { path: path.resolve(this.basePath, routePath), query: query }
- }
- return path.resolve(this.basePath, routePath)
- }
- }
- }
- script>