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

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

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

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代码部分(只截取了菜单部分)

      <a-menu theme="dark" 
        :openKeys="openKeys" // 重点 当前展开的菜单
        mode="inline"
        @openChange="onOpenChange" // 重点 当可以展开的菜单被点击时
        :defaultSelectedKeys="defaultSelectedKeys" // 默认选中的菜单
        style="width: 100%"
       >
      <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.handleData(result) // 处理数据
  },
  methods: {
  	// 处理数据展开应展开的菜单
    handleData(result) {
      function loop(list, keys = []) {
        // 循环【顶级菜单数组列表】 循环的数组下标用i表示
        // keys参数为当前菜单的所有上级菜单的router(用作openKeys的值)
        for (let item of list) {
          if (item.router === this.$route.path) {
          	// 如果路由path与item.router相等则直接返回当前路由的所有上级的router
            return [...keys]
		  } else if (item.children && item.children.length) {
		    // 如果item.router不等于当前$router.path则递归调用loop函数,传入item.children、[...keys, item.router]
		    let tempResult = loop(item.children, [...keys, item.router])
		    if (tempResult !== false) {
		      return tempResult
		    }
		  }
        }
        return false
      }
      this.openKeys = loop(result)
    },
    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)
    }
  }
}
Ant Design Vue 的 Menu 组件中,三级菜单默认情况下是不会展开的,需要用户手动点击才能展开。如果想要实现三级菜单展开不会自动折叠,可以考虑通过编写自定义的 Menu 组件来实现。 具体实现步骤如下: 1. 创建一个自定义的 Menu 组件,继承 Ant Design Vue 的 Menu 组件。 ```javascript import { Menu } from 'ant-design-vue'; export default { name: 'CustomMenu', extends: Menu, // ... }; ``` 2. 在组件的 data 中添加一个变量,用于存储当前展开菜单项的 key 数组。 ```javascript export default { // ... data() { return { // 存储当前展开菜单项的 key 数组 openKeys: [], }; }, // ... }; ``` 3. 实现 Menu 组件的 open-change 事件处理方法,用于更新 openKeys 数组的值。 ```javascript export default { // ... methods: { handleMenuOpenChange(openKeys) { this.openKeys = openKeys; }, }, // ... }; ``` 4. 在 Menu 组件的模板中,将 openKeys 数组绑定到 Menu 组件的 openKeys 属性上。 ```html <template> <a-menu :open-keys="openKeys" @open-change="handleMenuOpenChange"> <slot></slot> </a-menu> </template> ``` 5. 在 Menu.Item 组件上添加一个 slot-scope 属性,用于获取当前菜单项的 key。 ```html <a-menu-item v-for="item in menuData" :key="item.key" :data="item"> <template slot-scope="{ key }"> {{ item.title }} <custom-menu v-if="item.children" :menu-data="item.children" :default-open-keys="[key]"> <template slot-scope="{ key }"> <a-menu-item v-for="child in item.children" :key="child.key" :data="child"> {{ child.title }} </a-menu-item> </template> </custom-menu> </template> </a-menu-item> ``` 6. 创建一个 CustomMenu 组件,继承 Ant Design Vue 的 Menu 组件,并将其作为三级菜单的容器组件。 ```javascript import { Menu } from 'ant-design-vue'; export default { name: 'CustomMenu', extends: Menu, // ... }; ``` 7. 在 CustomMenu 组件的 data 中添加一个变量,用于存储当前展开菜单项的 key 数组。 ```javascript export default { // ... data() { return { // 存储当前展开菜单项的 key 数组 openKeys: [], }; }, // ... }; ``` 8. 实现 CustomMenu 组件的 open-change 事件处理方法,用于更新 openKeys 数组的值。 ```javascript export default { // ... methods: { handleMenuOpenChange(openKeys) { this.openKeys = openKeys; }, }, // ... }; ``` 9. 在 CustomMenu 组件的模板中,将 openKeys 数组绑定到 Menu 组件的 openKeys 属性上。 ```html <template> <a-menu :open-keys="openKeys" @open-change="handleMenuOpenChange"> <slot></slot> </a-menu> </template> ``` 10. 最后,在 Menu.Item 组件上添加一个 slot-scope 属性,用于获取当前菜单项的 key,并将其传递给 CustomMenu 组件。 ```html <a-menu-item v-for="item in menuData" :key="item.key" :data="item"> <template slot-scope="{ key }"> {{ item.title }} <custom-menu v-if="item.children" :menu-data="item.children" :default-open-keys="[key]"> <template slot-scope="{ key }"> <a-menu-item v-for="child in item.children" :key="child.key" :data="child"> {{ child.title }} </a-menu-item> </template> </custom-menu> </template> </a-menu-item> ``` 这样,就可以实现三级菜单展开不会自动折叠的效果了。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值