Ant Design Vue 实现菜单栏根据url变化自动高亮和展开

转载于:

https://blog.csdn.net/qq_35069272/article/details/104990576

以下是我根据自己的情况作了适当的修改:

实现的功能:

  • 刷新后保持菜单选中
  • 当从一个页面 push到另一个页面时,页面跳转,对应的菜单高亮
  • 浏览器输入url后,页面跳转,对应的菜单高亮
<template>
  <a-layout id="layout" style="min-height: 100vh">
    <a-layout-sider v-model="collapsed" collapsible>    
      <a-menu 
          theme="dark" 
          :openKeys="openKeys"   // 重点: 当前展开的菜单
          @openChange="onOpenChange"    // 重点: 当可以展开的菜单被点击时
          v-model="SelectedKeys"     // 选中的菜单
          mode="inline">
        <template v-for="item in menuItems">
          <!--  有二级菜单的一级菜单  -->
          <a-sub-menu v-if="item.children && item.is_active" :key="item.id">
            <span slot="title">
              <a-icon :type="item.icon" /><span>{{ item.name }}</span>
            </span>
            <!-- 二级菜单 -->
            <template v-for="subItem in item.children">
              <a-menu-item v-if="subItem.is_active" :key="subItem.path" :index="subItem.path">
                <router-link :to="{ path: subItem.path }">
                  <a-icon v-if="subItem.icon" :type="subItem.icon" />
                  <span>{{ subItem.name }}</span>
                </router-link>
              </a-menu-item>
            </template>
          </a-sub-menu>
          <!--没有二级菜单的一级菜单-->
          <a-sub-menu v-if="!item.children && item.is_active" :key="item.id + ''">
            <span slot="title">
              <a-icon :type="item.icon" /><span>{{ item.name }}</span>
            </span>
          </a-sub-menu>
        </template>
      </a-menu>
    </a-layout-sider>
    <a-layout>
    </a-layout>
  </a-layout>
</template>

<script>
import { MenuTree } from '@/api/rbac'

export default {
  data () {
    return {
      SelectedKeys: [this.$route.path],
      openKeys: [],
      menuItems: [],
      submenu: [],
    }
  },
//  通过结果从后端获取菜单
// 成功后的格式为  
//     [
//     {
//         "id": 2,
//         "name": "系统管理",
//         "icon": "setting",
//         "path": "",
//         "is_active": true,
//         "sort": 2,
//         "pid": null,
//         "children": [
//             {
//                 "id": 3,
//                 "name": "用户管理",
//                 "icon": "user",
//                 "path": "/user/manage",
//                 "is_active": true,
//                 "sort": 1,
//                 "pid": 2
//             },
//         ]
//     }
// ]
  async created () {
    await MenuTree().then(res => {
      this.menuItems = res
      for (const item of res) {
        if (item.children) {
          for (const subitem of item.children) {
            if (subitem.path === this.$route.path) {
              this.openKeys = [subitem.pid]     // 此时this.openKeys为父菜单的id(因为父菜单key为:key="item.id"),此时当在浏览器输入url时,会展开此子菜单的父菜单
            }
          }
        }
      }
    })
  },
  watch: {
    '$route.path': function () {
      this.SelectedKeys = [this.$route.path]     // 此处监听路由变化,是当push跳转时,是跳转后url的菜单高亮
    }
  },
  methods: {
    onOpenChange (openKeys) {
    // 当菜单被展开时触发此处
      /* 
      经测试传入的变量openKeys是数组 点击已经展开的菜单时传入的是空数组
      点击未展开的菜单时传入的是【当前展开菜单的key,点击的菜单key】
      下面的if判断用openKeys === [] 无效 所以我只能判断数组length是否等于0
      */
      if (openKeys.length !== 0) {
        this.openKeys = [openKeys[1]]
      } else {
        this.openKeys = ['']
      }
    }
  },
}
</script>

<style>

</style>
原文地址:https://www.cnblogs.com/deny/p/14940758.html