当前位置: 首页 > news >正文

如何在vue3中实现动态路由

 选用技术栈vue3+typescripy+element-plus ui+router 4

编写通用动态路由菜单

目标:根据路由配置信息,自动生成菜单内容。实现更通用、更自动的菜单配置。
通用路由菜单组件实现步骤
1.提取通用路由文件
2.菜单组件读取路由,动态渲染菜单项
3.绑定跳转事件
4.同步路由的更新到菜单项高亮
5.按需补充更多能力

(1)提取通用路由文件

 把 router/index.ts 中的路由变量定义为单独的文件 routes.ts,代码如下:

export const routes: Array<RouteRecordRaw> = [{path: '/shouye',name: '首页',component: Shouye,},{path: '/keichengxuexi',name: '课程学习',component: Courselearning,},
}

然后在 router/index.ts 中引入 routes.


(2)菜单组件读取路由,动态渲染菜单项

<script setup lang= ts >
import { routes }from "../router/routes";
</script>

模板中根据路由数组渲染菜单:

<el-menu-item v-for="item in routes" :key="item.path">{{ item.name }}
</el-menu-item>

(3)绑定跳转事件

import { useRoute, useRouter } from "vue-router";
const router = useRouter();// 路由跳转事件
const doMenuClick = (key: string) => {router.push({path: key,});
};

 模板修改:

<el-menumode="horizontal"@menu-item-click="doMenuClick"
>...
</el-menu>

(4)同步路由的更新到菜单项高亮

同步高亮原理:首先点击菜单项 => 触发点击事件并跳转更新路由 => 更新路由后,同步去更新菜单栏的高亮状态。

使用 Vue Router 的 afterEach 路由钩子实现:

const router = useRouter();// Tab 栏选中菜单项
const selectedKeys = ref(["/"]);
// 路由跳转后,更新选中的菜单项
router.afterEach((to, from, failure) => {selectedKeys.value = [to.path];
});

模板引入变量:

<el-menumode="horizontal":default-active="selectedKeys[0]" @menu-item-click="doMenuClick"
>
</el-menu>

还可以给路由菜单组件增加更多能力。

(5)按需补充更多能力(可以参考网上的框架),比如根据配置控制菜单的显隐。

利用 routes 配置的 meta 属性实现。routes.ts 中给路由配置新增一个标志位 hideInMenu,用于判断路由是否显隐:

  {path: "/hide",name: "隐藏页面",component: HomeView,meta: {hideInMenu: true,},},

 然后根据该标志位过滤路由数组,仅保留需要展示的元素。

不要用 v-for + v-if 去条件渲染元素,这样会先循环所有的元素,导致性能的浪费。

// 展示在菜单的路由数组
const visibleRoutes = routes.filter((item) => {if (item.meta?.hideInMenu) {return false;}return true;
});

整体的代码实现如下

菜单栏组件GlobalHeader.vue

<template><div id="globalHeader"><el-menu :default-active="selectedKeys[0]" class="el-menu-demo" mode="horizontal" @select="handleSelect"background-color="rgb(255, 165, 104)" text-color="white"active-text-color="rgb(0,0,51)"><el-menu-item v-for="item in visibleRoutes" :key="item.path"><el-sub-menu v-if="item.children" :index="item.path"><template #title>{{ item.name }}</template><el-menu-item v-for="child in item.children" :key="child.path" @click="doMenuClick(`${item.path}/${child.path}`)">{{ child.name }}</el-menu-item></el-sub-menu><template v-else><el-menu-item @click="doMenuClick(item.path)">{{ item.name }}</el-menu-item></template></el-menu-item></el-menu></div>
</template>

 上述菜单由于加入了子菜单的原因,所以增加了一层if的判断逻辑。这个路由下是否还有子路由。

<script setup lang="ts">
import { routes } from '../router/routes'
import { useRouter } from 'vue-router'
import { ref } from 'vue'const handleSelect = (key: string, keyPath: string[]) => {console.log(key, keyPath)
}const router = useRouter();
//当前选中的菜单项
const selectedKeys = ref(["/"]);
//路由跳转时,选中菜单项1
router.afterEach((to, from) => {selectedKeys.value = [to.path];
})//展示在菜单中的路由
const visibleRoutes = routes.filter((item) => {if (item.meta?.hideInMenu) {console.log('隐藏的菜单:', item.name);return false;}return true;
})//点击菜单跳转到对应页面
const doMenuClick = (key: string) => {router.push({path: key,});
}</script>

routes.ts 路由组件

import {  RouteRecordRaw } from "vue-router";
import Shouye from "../views/Shouye.vue";
import Courselearning from "../views/Courselearning.vue";//vue3引入路由的方式
export const routes: Array<RouteRecordRaw> = [{path: '/shouye',name: '首页',component: Shouye,},{path: '/keichengxuexi',name: '课程学习',component: Courselearning,meta:{hideInMenu: true,},},{path: '/ketangxiaolian',name: '课堂小练',children: [{path: '/network-world',name: '神奇的网络世界',component: Networld,},{path: '/internet',name: '走进互联网',component: Internet,},{path: '/information-collection',name: '网上收集信息',component: Collectinformation,},{path: '/communication',name: '网上交流信息',component: Communication,},{path: '/soho-network',name: '组件SOHO网络',component: Sohonetwork,},]},
}

 


 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 论文复现-基于决策树算法构建银行贷款审批预测模型(金融风控场景)
  • 分布式技术栈、微服务架构 区分
  • 一篇文章Scala语言入门
  • Day59 动态规划part12
  • 快速解决找不到krpt.dll,无法继续执行代码问题
  • git 添加本地分支, clean
  • 02-android studio实现下拉列表+单选框+年月日功能
  • 短信验证码实现
  • ubuntu常用命令
  • python操作SQLite3数据库进行增删改查
  • Java中的大数据处理与分析技术
  • 指针(一)
  • 探索 Apache Paimon 在阿里智能引擎的应用场景
  • 2024年7月1日 (周一) 叶子游戏新闻
  • 鸿蒙开发管理:【@ohos.account.osAccount (系统帐号管理)】
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • es的写入过程
  • Git学习与使用心得(1)—— 初始化
  • Hexo+码云+git快速搭建免费的静态Blog
  • linux安装openssl、swoole等扩展的具体步骤
  • Mocha测试初探
  • mysql常用命令汇总
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • React16时代,该用什么姿势写 React ?
  • ReactNative开发常用的三方模块
  • Redux 中间件分析
  • tab.js分享及浏览器兼容性问题汇总
  • VUE es6技巧写法(持续更新中~~~)
  • Vultr 教程目录
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 大快搜索数据爬虫技术实例安装教学篇
  • 后端_MYSQL
  • 机器学习学习笔记一
  • 离散点最小(凸)包围边界查找
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 浅谈web中前端模板引擎的使用
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 网络应用优化——时延与带宽
  • 网页视频流m3u8/ts视频下载
  • Semaphore
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​Java并发新构件之Exchanger
  • # .NET Framework中使用命名管道进行进程间通信
  • (2)nginx 安装、启停
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (Qt) 默认QtWidget应用包含什么?
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (二)WCF的Binding模型
  • (计算机网络)物理层
  • (一)、软硬件全开源智能手表,与手机互联,标配多表盘,功能丰富(ZSWatch-Zephyr)
  • (一)VirtualBox安装增强功能
  • (转)Oracle 9i 数据库设计指引全集(1)