技术点:动态加载路由
目录
1.main.js 导入编写的js文件
import {createApp} from 'vue'
import App from './App.vue'
import router from "./router";
import "./router/permission";
const app = createApp(App)
app.use(router)
app.mount('#app')
2.router/index.js 创建路由
import {createRouter, createWebHistory} from "vue-router"
const staticRoutes = [
{
path: '/login',
component: () => import('@/view/login/index.vue'),
name:'login',
meta: {title: '登录', keepAlive: false}
},
{
path: '/register',
name: 'register',
component: () => import('@/view/register/index.vue'),
meta: {title: '注册', keepAlive: false}
},
];
const router = createRouter({
history: createWebHistory("/"),
routes: staticRoutes,
scrollBehavior(to, from, savePosition) {
if (savePosition) {
//解决页面从列表页跳转到详情页返回,初始在原来位置
return savePosition
} else {
//解决页面跳转后页面高度和前一个页面高度一样
return {x: 0, y: 0}
}
}
});
export default router
3.router/getAsyncRouter.js 挂载后台传来的路由
// 匹配view里面所有的.vue文件
const modules = import.meta.glob('./../view/**/*.vue')
// 遍历后台传来的路由字符串,转换为组件对象
export function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
// filter() 创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
return asyncRouterMap.filter(route => {
if (route.component) {
route.component = loadView(route.component)
}
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type)
} else {
delete route['children']
delete route['redirect']
}
return true
})
}
export const loadView = (view) => {
let res;
for (const path in modules) {
const dir = path.split('view')[1].split('.vue')[0];
if (dir === view) {
res = () => modules[path]();
}
}
return res;
}
4.router/permission.js 模拟获取后台数据及路由跳转
import router from './index.js'
import {filterAsyncRouter} from "./getAsyncRouter.js";
// 导航守卫 to:目标路由 from:正要离开的路由
router.beforeEach( (to, from, next) => {
//模拟获取的动态路由数据
const menuList = [
{
path: '/home',
name: 'home',
component: '/home/index',
meta: {title: '主页', keepAlive: false},
redirect:'/home/children2',
children: [{
path: 'children1',
name: 'children1',
component: '/home/children1/index',
meta: {title: 'children1', keepAlive: false},
}, {
path: 'children2',
name: 'children2',
component: '/home/children2/index',
meta: {title: 'children2', keepAlive: false},
}]
},
]
let menuRouter = filterAsyncRouter(menuList)
menuRouter.forEach(route => {
router.addRoute(route)
})
next()
})
5.home/index.vue 编写测试按钮
<template>
<div>home</div>
<button @click="$router.push({name:'login'})">去login</button>
<button @click="$router.push({name:'children2'})">去children2</button>
<button @click="$router.push({name:'children1'})">去children1</button>
<router-view v-slot="{ Component }">
<component :key="$route.name" :is="Component"/>
</router-view>
</template>
<script setup>
</script>
<style scoped>
</style>
易错点:
(1)const modules = import.meta.glob('./../view/**/*.vue') 路径不对
(2)home/index.vue 缺少 router-view
(3)permission.js 模拟获取的动态路由数据,路径属性名需与router.js中一样,转向为redirect:'路径',
注意:
(1)添加路由后,输出全部路由数组,会显示数组没有加上(是没有问题的,一样可以跳转到指定页面)
(2)如果没有跳转成功,试试把 添加路由后的next() 换成 next({ ...to, replace: true })