vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > ElementUI之菜单(Menu)使用

ElementUI之菜单(Menu)的使用方式

作者:xrkhy

文章介绍Vue项目中ElementUI菜单默认精确路由匹配,与router-link的模糊匹配不同,提供三种解决方案:计算属性、高阶组封装、子菜单递归,并根据项目复杂度推荐使用方式

项目创建

创建项目

我的node.js使用的是20.18.0版本

我的 @vue/cli使用的是5.0.8版本

vue create elementui-draw-pages

运行项目

npm run serve

整理目录

删除src/assets中的所有logo.png

删除src/components中的所有文件

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = []

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

删除src/views中所有文件

<template>
  <div id="app">
    初始化页面
  </div>
</template>

<style lang="scss">

</style>

引入ElementUI

安装ElementUI

可以参考我之前的文章Vue2使用cli脚手架引入ElementUI

我直接全局安装了

npm i element-ui -S

引入ElementUI

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});

测试是否安装成功

<template>
  <div id="app">
    <el-button type="primary">测试</el-button>
  </div>
</template>

<script>

export default {
}
</script>

<style lang="scss">
</style>

编写路由搭架子

一级路由

<template>
  <div>
    <h1>一级路由 Login</h1>
  </div>
</template>

<script>
export default {
  
}
</script>

<style>

</style>
<template>
  <div>
    <h1> 一级路由 前台</h1>
    <router-view></router-view>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
<template>
  <div>
    <h1>一级路由 后台</h1>
    <router-view></router-view>
  </div>
</template>

<script>
export default {};
</script>

<style lang="scss" scope>
</style>

二级路由

<template>
  <div>
    <h2>二级路由Home</h2>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
<template>
  <div>
    <h2>二级路由漫画</h2>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
<template>
  <div>
    <h2>二级路由 用户管理</h2>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
<template>
  <div>
      <h2>二级路由Provider</h2>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>

修改src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  // 重定向
  {path: '/', redirect: '/login'},
  {path: '/login', component: () => import('@/views/Login.vue')},
  {path: '/admin', component: () => import('@/views/admin/adminIndex.vue'),
    redirect: '/admin/user', // 重定向两种写法 推荐这种写法简单
    children:[
      {path: 'user', component: () => import('@/views/admin/user.vue')},
      {path: 'provider', component: () => import('@/views/admin/provider.vue')},
    ]
  },
  {path: '/front', component: () => import('@/views/front/frontIndex.vue'),
    children:[
      {path: '/front', redirect: '/front/home'},// 重定向两种写法
      {path: '/front/home', component: () => import('@/views/front/home.vue')},
      {path: '/front/caricature', component: () => import('@/views/front/caricature.vue')}
    ]
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

使用 ElementUI 中菜单组件

修改src/views/front/frontIndex.vue

<template>
  <div>
    <!-- <h1> 一级路由 前台</h1>
    <router-view></router-view> -->
    <el-container>
      <el-header>
        <!--
            router: 是否使用 vue-router 的模式,
            启用该模式会在激活导航时以 index 作为 path 进行路由跳转
          -->
          <!-- 
            这里 default-active 需要默认选中
            这里的default-active为什么不能写死呢?即 default-active="/front/home"
            因为路由是动态的,所以需要根据路由来动态设置
            如果写成上面的,那么路由切换的时候,菜单栏不会跟着切换。
            即出现  在http://localhost:8080/front/home页面已刷新,
                  默认选中变成了首页,但是还是展示漫画页面
          -->
          <!-- 
            mode: 模式,默认值 vertical(垂直展示) ,可选值 horizontal(水平展示)
          -->
          <!-- 
            background-color: 菜单栏背景色
            text-color: 菜单栏文字颜色
            active-text-color: 菜单栏激活的文字颜色
          -->
        <el-menu
          router
          :default-active="$route.path"
          class="el-menu-demo"
          mode="horizontal"
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#ffd04b"
        >
          <el-menu-item index="/front/home">首页</el-menu-item>
          <el-menu-item index="/front/caricature">漫画</el-menu-item>
        </el-menu>
      </el-header>
      <el-main>
        <router-view></router-view>
      </el-main>
    </el-container>
  </div>
</template>

<script>
export default {};
</script>

<style lang="scss" scoped>
.el-header{
  margin: 0;
  padding: 0;
}
</style>

修改src/views/admin/adminIndex.vue

<template>
  <div>
    <!-- <h1>一级路由 后台</h1>
    <router-view></router-view> -->
    <el-container>
      <el-header class="el-header-admin"> 后台管理 </el-header>
      <el-container>
        <el-aside width="200px">
          <!--
            router: 是否使用 vue-router 的模式,
            启用该模式会在激活导航时以 index 作为 path 进行路由跳转
          -->
          <!-- 
            这里 default-active 需要默认选中
            这里的default-active为什么不能写死呢?即 default-active="/admin/user"
            因为路由是动态的,所以需要根据路由来动态设置
            如果写成上面的,那么路由切换的时候,菜单栏不会跟着切换。
            即出现  在http://localhost:8080/admin/provider页面已刷新,
                  默认选中变成了用户管理,但是还是展示供应商管理页面
          -->
          <!-- 
            mode: 模式,默认值 vertical(垂直展示) ,可选值 horizontal(水平展示)
          -->
          <!-- 
            background-color: 菜单栏背景色
            text-color: 菜单栏文字颜色
            active-text-color: 菜单栏激活的文字颜色
          -->
          <el-menu
            router
            :default-active="$route.path"
            class="el-menu-demo"
            mode="vertical"
            background-color="#545c64"
            text-color="#fff"
            active-text-color="#ffd04b"
          >
            <el-menu-item index="/admin/user">用户管理</el-menu-item>
            <el-menu-item index="/admin/provider">供应商管理</el-menu-item>
          </el-menu>
        </el-aside>
        <el-main>
          <router-view></router-view>
        </el-main>
      </el-container>
    </el-container>
    
  </div>
</template>

<script>
export default {};
</script>

<style lang="scss" scope>
* {
  margin: 0;
  padding: 0;
}
.el-header-admin {
  background-color: #545c64;
  font-size: 30px;
  color: #fff;
  line-height: 60px;
}
.el-menu-demo {
  height: 90vh;
}
</style>

运行结果

高级用法

ElementUI 的菜单组件(el-menu)默认的​​路由匹配行为是精确匹配​​,而非 router-link的模糊匹配(即包含匹配)。不过,可以通过自定义逻辑模拟类似效果。

以下是具体分析及实现方案:

1 ElementUI 菜单的默认路由机制​

路由跳转​​:

​​激活状态匹配​​:

2 与 router-link模糊匹配的区别​

特性​router-link(默认)ElementUI 菜单(默认)
匹配模式​​模糊匹配(路径包含即激活)精确匹配(路径完全一致才激活)
​​配置方式​​无需额外配置需手动绑定 default-active
​​子路径激活​​支持(如 /user激活 /user/list)❌ 不支持

3 实现模糊匹配的解决方案​

方案一:自定义计算属性动态匹配​

通过监听路由变化,手动检查当前路径是否包含菜单项的 index值:

<template>
  <el-menu :default-active="activeMenu">
    <el-menu-item index="/user" @click="$router.push('/user')">用户管理</el-menu-item>
  </el-menu>
</template>

<script>
export default {
  computed: {
    activeMenu() {
      const route = this.$route.path;
      // 模糊匹配逻辑:若当前路径包含菜单项的 index,则激活该菜单
      if (route.includes('/user')) return '/user';
      return route;
    }
  }
};
</script>

优点​​:灵活控制匹配规则,支持多级路径。

方案二:扩展 el-menu的 default-active逻辑​

封装高阶组件,重写 default-active的匹配逻辑:

Vue.component('fuzzy-menu', {
  props: ['menus'],
  computed: {
    activePath() {
      return this.menus.find(menu => 
        this.$route.path.includes(menu.index)
      )?.index;
    }
  },
  render(h) {
    return h('el-menu', {
      props: { defaultActive: this.activePath }
    }, this.menus.map(menu => 
      h('el-menu-item', { props: { index: menu.index } }, menu.label)
    ));
  }
});

适用场景​​:需多处复用模糊匹配菜单时。

方案三:递归处理嵌套菜单​

对于多级菜单(el-submenu),递归遍历子节点检查路径:

function findActiveMenu(menus, path) {
  for (const menu of menus) {
    if (path.includes(menu.index)) return menu.index;
    if (menu.children) {
      const childActive = findActiveMenu(menu.children, path);
      if (childActive) return childActive;
    }
  }
}

适用场景​​:动态生成复杂树形菜单时。

总结​​

​​默认行为​​:ElementUI 菜单仅支持精确路由匹配,无法直接实现 router-link的模糊匹配。

​​自定义方案​​:

​​推荐场景​​:

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文