vue3动态路由的实现

一、登录获取路由信息

Login.vue中的登录按钮事件

const res = await http.post('/login', data)
if (res.data.code === 200) {
    //存菜单
    let menuList = res.data.data.routers 
    localStorage.setItem('menuList', JSON.stringify(menuList))
    store.commit("setMenuList", menuList);

    //存路由
    let routes = res.data.data.components
    localStorage.setItem('routes', JSON.stringify(routes))
    store.commit("setRouters", routes);

    router.push({
        path: "/dashboard"
    });
}

 二、渲染动态路由

router/index.js中定义基本的路由信息,动态生成的路由默认放在Home组件

1、未使用动态路由的写法 ,一般会把所有路由信息写到home的children数组中

import {createRouter, createWebHashHistory} from "vue-router";
import store from '../store/index'

const routes = [
    {
        path: "/login",
        name: "login",
        component: () => import ( /* webpackChunkName: "login" */ "../views/login/Login.vue"),
        meta: {
            title: '登录',
        },
    },
    {
        path: '/register',
        name: 'register',
        component: () => import(/* webpackChunkName: "register" */ '../views/login/Register.vue'),
        meta: {
            title: '注册',
        },
    },
    {
        path: "/home",
        name: "home",
        component: () => import ( "../components/Home.vue"),
        children: [
            {
                path: '/index',
                component: () => import('../views/Index.vue'),
                meta: {
                    title: 'Index',
                    requiresAuth: true
                }
            },
            {
                path: '/test',
                component: () => import('../views/Test.vue'),
                meta: {
                    title: 'Test',
                    requiresAuth: true
                }
            },
        ]
    }
];

const router = createRouter({
    history: createWebHashHistory(),
    routes
});

2、当使用动态路由时, 默认向Home.vue中添加children子路由

import {createRouter, createWebHashHistory} from "vue-router";
import store from '../store/index'
import dealWithRoute from "./dealWithRoute";

const routes = [
    {
        path: "/login",
        name: "login",
        component: () => import ( /* webpackChunkName: "login" */ "../views/login/Login.vue"),
        meta: {
            title: '登录',
        },
    },
    {
        path: '/register',
        name: 'register',
        component: () => import(/* webpackChunkName: "register" */ '../views/login/Register.vue'),
        meta: {
            title: '注册',
        },
    },
    {
        path: "/home",
        name: "home",
        component: () => import ( "../components/Home.vue"),
    }
];

const router = createRouter({
    history: createWebHashHistory(),
    routes
});

router.beforeEach中获取登录时所存储的数据

当生成动态路由后一旦刷新页面,页面会变成空白,需要重新从localStorage取值渲染

router.addRoute第一个参数是动态路由所在“位置”,是指定“位置”的name属性

router.beforeEach((to, from, next) =>   {
    // console.log('to, from', to, from);
    let isLoadRouters = store.state.asyncRoutesMark
    let token = sessionStorage.getItem('token')
    let routes = JSON.parse(localStorage.getItem('routes'))
    // 有token routes
    if (to.path == '/login') {
        next()
    } else {
        //用户已登录
        if (token && JSON.stringify(routes) != '[]') {
            if (isLoadRouters) {
                // console.log('路由已添加,直接跳转到目标页面');
                next()
            } else {
                //解决刷新页面空白
                //console.log('重新加载路由,并跳转到目标页');
                let route = JSON.parse(localStorage.getItem('routes'))
                store.commit('setRouters', route);
                store.commit('setAsyncRoutesMark', true);

                //添加动态路由
                let menuList = JSON.parse(localStorage.getItem('menuList'))
                dealWithRoute(menuList)

                next({...to,replace: true})
            }
        } else {
            // console.log('无登录信息,跳转到登录页');
            store.commit('setMenuList', []);
            store.commit('setAsyncRoutesMark', false);
            sessionStorage.setItem('token', '');
            localStorage.setItem('menuList', JSON.stringify([]));
            localStorage.setItem('routes', JSON.stringify([]));
            next(`/login`)
        }
    }

});

export default router;
//处理树形数据
//dealWithRoute.js

import router from './index';
import {RouterView} from "vue-router";

const dealWithRoute = (data, parent = 'home') => {
    for (let item of data) {
        //多级菜单
        if (item.children && item.children.length > 0) {
            router.addRoute(parent, {
                path: item.path,
                name: item.path.split('/')[1],
                component: RouterView,
                meta: {
                    title: item.name,
                    requiresAuth: true
                }
            })
            dealWithRoute(item.children, item.path.split('/')[1])

        } else {  //一级菜单
            router.addRoute(parent, {
                path: item.path,
                name: item.name,
                component: () => import(`../views/${item.component}`),
                meta: {
                    title: item.name,
                    requiresAuth: true
                }
            });
        }
    }
};

export default dealWithRoute;

 三、vuex代码

store/index.js

import {createStore} from 'vuex'

export default createStore({
    state: {
        asyncRoutesMark: false,
        menu: [],
        routers: []
    },
    mutations: {
        setAsyncRoutesMark(state, data) {
            state.asyncRoutesMark = data;
        },

        setMenuList(state, data) {
            state.menu = data
        },

        setRouters(state, data) {
            state.routers = data;
        }
    }, 
})

猜你喜欢

转载自blog.csdn.net/csdnyp/article/details/125558980