如何在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-menu
mode="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-menu
mode="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,
},
]
},
}
原文地址:https://blog.csdn.net/weixin_46918091/article/details/140237196
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!