Element: NavMenu 导航菜单 路由跳转后如何动态设置当前菜单高亮

Created on 29 Jan 2017  ·  23Comments  ·  Source: ElemeFE/element

请问个大神一个 navMenu的问题

如题, 路由跳转后如何动态设置当前菜单高亮?

Most helpful comment

history mode

..
      <el-menu class="nav right menu" :default-active="activeIndex"  mode="horizontal" :router="true" @select="handleSelect">
        <el-menu-item class="item" index="/home">首页</el-menu-item>
        <el-menu-item class="item" index="/service">产品服务</el-menu-item>
        <el-menu-item class="item" index="/news">新闻资讯</el-menu-item>
...


  computed: {
    activeIndex () {
      return '/'+this.$route.matched[0].path.split('/')[1]
    }
  }

All 23 comments

可以通过在 App watch router 变化,动态绑定 navMenu 的 defaultActive

@KentonYu +1,navMenu只是一个傀儡组件,建立与页面路由的映射需要自己去做

@baiyaaaaa NavMenu控制选中状态的是 activedIndex 这个属性吧,default-active动态更改没什么作用。如何动态更改activedIndex?

比如动态的二级菜单,暂时通过直接暴力操作对象,哈哈
https://github.com/tomieric/element-ui-magic/issues/1

$route (route) {
        // 通过路由地址
        // 默认只有二级
        let paths = route.path.split('/')
        const path = paths && paths.length ? paths.slice(0, 3).join('/') : route.path
        // element nav的数据是缓存的
        // 重新传入list并不会更新路由地址作为的key
        this.$refs.kzMenu.activedIndex = path
}

@tomieric this.$refs.kzMenukzMenu是如何找到的?

@theharveyz el-menu定义一个ref="kzMenu"

<el-menu
  ref="kzMenu"
...
>

@theharveyz 应该设置的是 defaultActive,activedIndex 是内部根据 defaultActive 更新的属性。

@baiyaaaaa 目前看并没有... 我感觉 @tomieric 也是遇到了这个问题,从而用了上面的方法

情景

有下列导航

  • 人员管理(e/index)

    • 添加人员(e/add)

    • 编辑人员(e/edit)

    • 权限控制(e/permission)

  • 报表管理(m/dayReport)

    • 每天汇总(m/dayReport)

    • 月汇总报表(m/monthReport)

比如有一级菜单人员管理, 报表管理

首页显示的二级菜单

  • 添加人员
  • 编辑人员
  • 权限控制

使用路由作为navMenukey

然后点击一级菜单报表管理

二级导航更新为

  • 每天汇总(m/dayReport)
  • 月汇总报表(m/monthReport)

我们设置:default-active="$route.path"

理应是切换路由后二级菜单中的每天汇总(m/dayReport)应该为高亮

但在这里并没有高亮

https://github.com/ElemeFE/element/blob/dev/packages/menu/src/menu.vue#L52

我们加打印可以看到item的值是undefined

我们打印this.items

{
    'e/add': ...,
    'e/edit': ...
}

并不是我们想象中的key值为

{
    'm/dayReport': ...,
    'm/monthReport': ...
}

根据Vue的响应式原理特性 https://cn.vuejs.org/v2/guide/reactivity.html

所以在https://github.com/ElemeFE/element/blob/dev/packages/menu/src/menu.vue#L52this.items[value]的值为undefiend

解题思路

  1. 一次性加载所有二级菜单,根据一级进行显示和隐藏
  2. key使用数组列表的索引(我遇到的问题是使用的接口返回来的菜单id),根据路由在当前二级菜单列表的索引位置一一对应
  3. 不得已使用$ref.tree.activeIndex,这方法是偷懒,项目赶得急

试一下在一级菜单上设置

:default-active="this.$route.matched[0].path"

本地测试了一下,发现可以。

使用计算属性可以兼容只有一级菜单的情况:

computed: {
      defaultActive () {
        if (this.$route.matched.length > 1) {
          return this.$route.matched[0].path;
        } else {
          return this.$route.path;
        }
      }
}

编译是从外层向内层的,所以default-active属性会先编译,此时menu-item还没有生成(因为是动态生成的),所以menu的this.items实际上是空的,导致无法highlight,这里存在一个时序的问题。

可以将default-active绑定的data上面,然后watch $route, 通过setTimeout来异步设置

<el-menu :default-active="defaultActive"></el-menu>
<script>
export default {
    data() {
        return  {
            defaultActive: ''
        }
    },
    watch: {
        '$route': (to) => {
            var self = this;
            setTimeout(() => {
                selt.defaultActive = to.fullPath;
            }, 200);
        }
    }
}
</script>

@tomieric you are correct,

history mode

..
      <el-menu class="nav right menu" :default-active="activeIndex"  mode="horizontal" :router="true" @select="handleSelect">
        <el-menu-item class="item" index="/home">首页</el-menu-item>
        <el-menu-item class="item" index="/service">产品服务</el-menu-item>
        <el-menu-item class="item" index="/news">新闻资讯</el-menu-item>
...


  computed: {
    activeIndex () {
      return '/'+this.$route.matched[0].path.split('/')[1]
    }
  }

我发现NavMenu中的菜单项都是dom写死的,如何通过json数据动态生成

详见menu.vue
由于activeIndex不在props中,因此无法绑定;能绑定的是defaultActive,但是,这只是设置默认值而已,无法正常更新,所以还是得操作activeIndex

this.$refs.sidemenu.activeIndex = name

PS:注意另有一个变量activedIndex,多了一个d,不要搞错了

@haledeng your solution works for me!

<template> <el-menu ref="menu">...</el-menu> </template>

  1. 如果没有二级导航就可以了,手动修改menu组件内部activedIndex的值

this.$refs.menu.activedIndex= 'xxx' (xxx 为el-menu-item的index属性) this.$router.push('xxx')

2.如果有二级导航, 就需要有一个展示二级栏目的动画效果,可以调用menu内部的initOpenedMenu方法
this.$refs.menu.activedIndex = 'xxx' this.$refs.menu.initOpenedMenu() this.$router.push('xxx')

1.

<el-menu ref="menu" :router="true" :default-active="$router.currentRoute.path">
</el-menu>

2.

watch: {
      '$route' (to) {
        this.$refs.menu.activeIndex = to.path
      }

比如动态的二级菜单,暂时通过直接暴力操作对象,哈哈
tomieric/element-ui-magic#1

$route (route) {
        // 通过路由地址
        // 默认只有二级
        let paths = route.path.split('/')
        const path = paths && paths.length ? paths.slice(0, 3).join('/') : route.path
        // element nav的数据是缓存的
        // 重新传入list并不会更新路由地址作为的key
        this.$refs.kzMenu.activedIndex = path
}

element版本2.6.3是用this.$refs.menu.activeIndex 少了个'd'

self

这个this 牛

好难

试一下在一级菜单上设置

:default-active="this.$route.matched[0].path"

本地测试了一下,发现可以。

使用计算属性可以兼容只有一级菜单的情况:

computed: {
      defaultActive () {
        if (this.$route.matched.length > 1) {
          return this.$route.matched[0].path;
        } else {
          return this.$route.path;
        }
      }
}

对于我有帮助

假设左侧的导航最多两层,要让访问 查看产品/编辑产品 页面时,菜单高亮在 产品列表 上
我的解决方案 https://github.com/PanJiaChen/vue-element-admin/issues/171#issuecomment-655265535

Was this page helpful?
0 / 5 - 0 ratings

Related issues

EdenSpark picture EdenSpark  ·  3Comments

zhguokai picture zhguokai  ·  3Comments

akaylh picture akaylh  ·  3Comments

yuchonghua picture yuchonghua  ·  3Comments

yubo111 picture yubo111  ·  3Comments