技术点:动态加载路由

目录

vue3/vite 动态路由——动态加载路由

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 })

发表回复