Antd vue左侧动态菜单刷新自动展开选中并只能展开一个

用ANTD-Vue做管理页面的左侧菜单 需要在刷新后也能保持左侧菜单被选中和展开 且只能展开一个菜单

成品效果图
Antd vue左侧动态菜单刷新自动展开选中并只能展开一个_第1张图片

1.在刷新后保持菜单选中

这个比较简单
ANTD的API中提供了一个defaultSelectedKeys参数
描述:初始选中的菜单项 key 数组
类型: string[] 自己手动实验得知意思就是在数组中填入字符串 例如[‘key’]
默认值为空

一级菜单和子菜单都有一个key属性,我后端返回的json数据中的router属性是每个菜单的路由跳转地址 也赋值给了菜单的key 这样点击菜单跳转后 用this.$route.path获取到的当前路由地址就和菜单的key一致了

在菜单标签中设置 defaultSelectedKeys属性指向this.$route.path即可完成

2.在刷新后如果当前选中的菜单是二级菜单则展开当前菜单的父菜单

可展开(有二级菜单)的一级菜单点击后会展开或收起 不会发生跳转

ANTD提供了两个api:

openKeys	当前展开的 SubMenu 菜单项 key 数组
defaultOpenKeys	初始展开的 SubMenu 菜单项 key 数组

两个api中的描述 一个是"当前" 另一个是"初始(默认)" ,试了半天后发现用defaultOpenKeys设置值后是只生效一次的 也就是说等如果设置defaultOpenKeys的对应属性为空 等ajax请求到数据后再去设置,菜单就不会变化了,所以不能用这个

openKeys
看来只能用openKeys了,我又发现一个小问题,设置openKeys后手动点击其他没展开的菜单,菜单不会有变化 这样就得用到另一个API

openChange	展开/关闭的回调

每次点击可展开/收起的菜单时都会触发这个属性所对应的函数,设置openKeys后再配合openChange切换菜单即可解决问题

具体请看代码
VUE html代码部分(只截取了菜单部分)

      
      <template v-for="item in menuList"> // 渲染菜单列表
        <a-menu-item v-if="item.children === false" :key="item.router"> // 顶级菜单
          <span>{{ item.name }}span>
        a-menu-item>
        <a-sub-menu v-else :key="item.router"> // 可以展开的二级菜单
          <span slot="title"><span>{{ item.name }}span>span>
          <a-menu-item v-for="menuChildren in item.children" :key="menuChildren.router">{{ menuChildren.name }}a-menu-item>
        a-sub-menu>
      template>
      a-menu>

后端返回的JSON数据格式:

[
    {
        "name": "首页",
        "router": "/home/index",
        "children": false
    },
    {
        "name": "商品管理",
        "router": "/shop",  // 点击这个菜单不会跳转 只会展开 此处的router是为了设置key属性
        "children": [
            {
                "name": "商品分类",
                "router": "/home/shopClass"
            },
            {
                "name": "商品列表",
                "router": "/home/shopList"
            }
        ]
    },
    {
        "name": "个人设置",
        "router": "/user",
        "children": [
            {
                "name": "我的资料",
                "router": "/home/userEdit"
            },
            {
                "name": "登录记录",
                "router": "/home/userLoginRecord"
            }
        ]
    }
]
export default {
  data() {
    return {
      defaultSelectedKeys: [this.$route.path],
      openKeys: [''],
      menuList: [] // 此处为动态获取的菜单数组
    }
  },
  async created() {
    const result = await this.$http.post('home/menuList') // post后端服务器获取菜单数据
    this.menuList = result // 给data里面的菜单数组赋值数据
    this.xhmenu(result) // 处理数据 请原谅这让人看不懂的命名 o(╥﹏╥)o
  },
  methods: {
    xhmenu(result) {
      for (let i = 0; i < this.menuList.length; i++) { 
      //循环【顶级菜单数组列表】 循环的数组下标用i表示
        if (result[i].children !== false) {  
        // 如果这个菜单没有【子菜单】 就不继续了(没有子菜单就是【点击可跳转页面但不会展开】的顶级菜单)
          for (let y = 0; y < result[i].children.length; y++) {  
          // 循环【顶级菜单】的子菜单数组(二级菜单)数组下标用y表示
            if (result[i].children[y].router === this.$route.path) { 
            // 如果子菜单的router数据和当前路由地址一样 则断定现在的页面就停留在这个数组对应的菜单中
              this.openKeys = [result[i].router]
              // 那么就把【顶级菜单(循环数组下标为i)的router属性】赋值给this.openKeys【data中当前展开的菜单】
            }
          }
        }
      }
    },
    onOpenChange(openKeys) {  // 当菜单被展开时触发此处
      /* 
      经测试传入的变量openKeys是数组 点击已经展开的菜单时传入的是空数组
      点击未展开的菜单时传入的是[当前展开菜单的key,点击的菜单key]
      下面的if判断用openKeys === [] 无效 所以我只能判断数组length是否等于0
      */
      if (openKeys.length !== 0) {  
        this.openKeys = [openKeys[1]]
      } else {
        this.openKeys = ['']
      }
    },
    clickItem(obj) {
      this.$router.push(obj.key)
    }
  }
}

你可能感兴趣的:(Antd vue左侧动态菜单刷新自动展开选中并只能展开一个)