Vue3实现动态切换Menu

Vue3动态切换Menu的相关问题

项目中需要使用一个顶部导航栏和侧边栏,顶部导航栏来控制侧边栏的生成,于是需要动态切换

我是直接根据路由文件来控制整个菜单的生成结构,首先定义一下顶部导航栏的信息,他的key需要与路由的顶级name匹配,方便切换

// APP.vue

// 顶部导航栏信息
const navBarMenuList = [
  {
    name: 'Home',
    title: '应用分析'
  },

  {
    name: 'AppManage',
    title: '应用管理'
  }
]

路由文件中,给每个需要选中的菜单项添加上activeMenu,使用path作为值,同时这里我的需求中需要事件管理不展示子菜单,所以额外配置了一个showchild

export default [
  {
    path: '/appManage',	// 顶级路由(请让我这样简称)
    redirect: '/appManage/gameBaseInfo',
    name: 'AppManage',	// 这里与navBarMenu的name对应
    children: [
      {
        path: 'gameBaseInfo',	// 次级路由
        name: 'GameBaseInfo',
        icon: 'Memo',
        cnName: '基本信息',
        component: () => import('@/views/AppManage/BaseInfoView.vue'),
        meta: {
          activeMenu: 'gameBaseInfo',	// 用于给菜单的index项赋值,同时对应这个路由的地址
          needKeepAlive: true
        }
      },
      {
        path: 'eventManage',
        name: 'EventManage',
        icon: 'Management',
        cnName: '事件管理',
        showChild: false,	// 是否需要展示子菜单
        component: () => import('@/views/AppManage/EventManageView.vue'),
        redirect: '/appManage/eventManage/eventTable',
        meta: {
          needKeepAlive: true,
          activeMenu: 'eventManage'
        },
        children: [
          {
            path: 'eventDetail/:eventID?', // 子路由
            name: 'EventDetail',
            component: () => import('@/views/AppManage/EventDetailsView.vue')
          },
          {
            path: 'eventTable',
            name: 'EventTable',
            component: () => import('@/views/AppManage/EventMangeTable.vue')
          }
        ]
      }
    ]
  }
]

菜单的跳转不使用el-menu自带的router模式,自己使用route-link来实现跳转,跳转的路由则直接是由:顶级路由 + 次级路由+子路由形成。default-active一定要开启,以此来作为我们切换的根据,然后根据路由文件中有无children来判断是否生成子菜单。每个菜单项的index则对应路由文件中的activemenu,当路由切换后,defaultactive会自动计算出当前应该选中哪个菜单项。判断条件中的item.showchild是因为我有些菜单需要不展示子菜单。

<script lang='ts' setup>
// 顶部导航栏的选中情况
const navBarSelect = ref<string>('Home') 

// 路由信息,同时也是侧边栏生成的依据信息
const menuList = reactive<Array<any>>([])

// 顶部导航栏信息
const navBarMenuList = [
  {
    name: 'Home',
    title: '应用分析'
  },

  {
    name: 'AppManage',
    title: '应用管理'
  }
]

// 侧边栏跳转路由的基本路由
const basePath = ref<string | undefined>()

/**
 * @description: 创建侧边栏menu
 * @return {*}
 */
const createdMenuList = () => {
  let routes = router.options.routes // 获取路由信息
  let activeMenu = routes.find((item) => {
    return item.name === navBarSelect.value // 根据顶部导航栏的选中情况来选择选中哪个具体的路由信息,可以打印自己看一下
  })
  basePath.value = activeMenu?.path // 找到需要激活的菜单的路由,后续用来拼接需要跳转的路由
  menuList.splice(0, menuList.length, ...(activeMenu?.children as Array<any>)) // 清空原来的路由信息,并且加入新选中的
}
    
// 默认选中,他根据路由文件中的meta的activeMenu来判断当前选中的那个菜单
const defaultActive = computed(() => {
  return route.meta.activeMenu
})

</script>
   <!-- 顶部导航栏 -->
        <div class="navBarMenu">
          <el-menu
            :default-active="navBarSelect"
            class="el-menu-demo"
            mode="horizontal"
            @select="changeNavBar"
          >
            <el-menu-item
              v-for="item in navBarMenuList"
              class="navBarMenuItem"
              :index="item.name"
              >{{ item.title }}</el-menu-item
            >
          </el-menu>
        </div>
      <!-- 侧边栏 -->
<el-menu
          :default-active="defaultActive"
          class="sideBar"
          :collapse="isCollapse"
          ref="siderBar"
        >
          <template v-for="(item, index) in menuList">
            <el-sub-menu :index="`${index}`" v-if="item.children && item.showChild">
              <template #title>
                <el-icon><component :is="item.icon"></component></el-icon>
                <span>{{ item.cnName }}</span>
              </template>
              <router-link
                style="text-decoration: none"
                v-for="val in item.children"
                :to="{ path: basePath + '/' + item.path + '/' + val.path }"
                :key="index"
              >
                <el-menu-item :index="val.path">{{ val.cnName }}</el-menu-item>
              </router-link>
            </el-sub-menu>

            <router-link
              style="text-decoration: none"
              v-else
              :to="{ path: basePath + '/' + item.path }"
              :key="index"
            >
              <el-menu-item :index="item.path">
                <template #title>
                  <el-icon><component :is="item.icon" /></el-icon>
                  <span class="menuTitle">{{ item.cnName }}</span>
                </template>
              </el-menu-item>
            </router-link>
          </template>
          <div class="sideBarFold" @click="changeCollapse">
            <el-icon :size="25"><Fold /></el-icon>
          </div>
        </el-menu>

如果还有不清楚地地方可以打印一下routes,看一下就明白了。本人也是小菜鸡一枚,欢迎讨论。

实现菜单页面切换,可以使用Vue.js和Element UI中的el-menu组件。 1. 首先,在Vue.js中定义一个数据对象,用来存储菜单选项和对应的页面路由: ``` data() { return { menuItems: [ { index: 'home', title: '首页', route: '/' }, { index: 'about', title: '关于我们', route: '/about' }, { index: 'contact', title: '联系我们', route: '/contact' } ] } } ``` 2. 在模板中,使用el-menu组件来渲染菜单。设置mode属性为horizontal,表示菜单水平排列;设置default-active属性为当前选中的菜单项的index值: ``` <el-menu :default-active="$route.path" mode="horizontal"> <el-menu-item v-for="item in menuItems" :key="item.index" :index="item.route">{{ item.title }}</el-menu-item> </el-menu> ``` 3. 在路由配置中,定义对应的页面组件,并设置路由路径为菜单项的route值: ``` const routes = [ { path: '/', component: Home }, { path: '/about', component: About }, { path: '/contact', component: Contact } ] ``` 4. 最后,在页面组件中,使用Vue.js的路由功能来实现页面切换。例如,在点击菜单项时,使用this.$router.push()方法将路由切换到对应的页面: ``` methods: { handleMenuSelect(index) { this.$router.push(index) } } ``` 完整代码示例: ``` <template> <el-menu :default-active="$route.path" mode="horizontal" @select="handleMenuSelect"> <el-menu-item v-for="item in menuItems" :key="item.index" :index="item.route">{{ item.title }}</el-menu-item> </el-menu> </template> <script> import Home from './Home.vue' import About from './About.vue' import Contact from './Contact.vue' export default { data() { return { menuItems: [ { index: 'home', title: '首页', route: '/' }, { index: 'about', title: '关于我们', route: '/about' }, { index: 'contact', title: '联系我们', route: '/contact' } ] } }, methods: { handleMenuSelect(index) { this.$router.push(index) } }, components: { Home, About, Contact } } </script> <style scoped> /* 样式 */ </style> ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值