vue动态路由简单记录
原有路由文件 ./router.ts
import VueRouter from 'vue-router';
export const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
redirect: '/test**',
},
{
path: '/login',
component: (Lazy => ({ render: h => h(Lazy) }))(defineAsyncComponent(() => import('./login.vue'))),
},
{
path: '/aa',
component: (Lazy => ({ render: h => h(Lazy) }))(defineAsyncComponent(() => import('./aa.vue'))),
},
{
path: '/bb',
component: (Lazy => ({ render: h => h(Lazy) }))(defineAsyncComponent(() => import('./bb.vue'))),
},
{ path: '*', redirect: '/' },
],
});
// 在使用的的地方调用
import {router} from './router';
new Vue({
router,
pinia,
render: h => h(App),
}).$mount('#app');
使用动态路由,将文件分为3份,baseRouter.ts, dynamicRoute.ts, index.ts,新建router文件夹,创建以上3个文件。
baseRouter.ts 配置基础路由
const routes = [
{
path: '/',
redirect: '/test**',
},
{
path: '/login',
component: (Lazy => ({ render: h => h(Lazy) }))(defineAsyncComponent(() => import('./login.vue'))),
},
{
path: '*',
name: '404',
component: ErrorPage
}
];
export default routes;
dynamicRoute.ts 动态路由逻辑。const modules = import.meta.glob('../views/**/*.vue')
vite框架使用,不然在动态路由中直接引用组件打包后会导致动态组件页面不显示。import.meta.glob文档地址
const modules = import.meta.glob('../views/**/*.vue');
import { defineAsyncComponent } from '@vue/composition-api';
import routes from './baseRouter';
const RouterPlugin = function () {
this.$router = null;
};
RouterPlugin.install = function (router, store) {
this.$router = router;
// store 如果需要使用store 可以传入
// this.$store = store;
this.$router.$dynamicRoute = {
// 全局配置
safe: this,
// 动态路由,需要在登录之后调用
formatRoutes: function (aMenu = []) {
// 此处所有的 aMenu 只有子元素可以点击
const getChild = list => {
let childList = [];
list.forEach(item => {
if (item.children && item.children.length) {
childList = childList.concat(getChild(item.children));
} else {
childList = childList.concat(item);
}
});
return childList;
};
let childList = getChild(aMenu);
let oRouter = [];
childList.forEach(item => {
oRouter.push({
path: `${item.menuPath}`,
component: (Lazy => ({ render: h => h(Lazy) }))(defineAsyncComponent(modules[`../router1/${item.url}.vue`])),
});
});
let aRouter = {
path: '/router1',
name: 'router1Page',
component: (Lazy => ({ render: h => h(Lazy) }))(
defineAsyncComponent(modules['../router1/index.vue'])
),
children: oRouter,
};
this.safe.$router.addRoute(aRouter);
// 查看配置之后的所有路由
console.log(this.safe.$router.getRoutes());
},
};
};
export default RouterPlugin;
index.ts 文件配置
import Vue from 'vue';
import VueRouter from 'vue-router';
import baseRoutes from './baseRouter';
import RouterPlugin from './dynamicRoute';
Vue.use(VueRouter);
const createRouter = () => {
return new VueRouter({
// scrollBehavior 处理移动位置
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition;
} else {
return {
x: 0,
y: to.meta.savedPosition || 0,
};
}
},
routes: [...baseRoutes],
mode: 'history', //
});
};
let router = createRouter();
/**
resetRouter函数用于重置路由,每一次动态配置路由之前要先重置路由
**/
export function resetRouter() {
const newRouter = createRouter();
router.match = newRouter.match; // reset router
// store 使用vuex 或者 pinia
RouterPlugin.install(router, store);
}
/**
* 以下是缓存处理,看情况使用
当用户刷新页面时,路由数据会丢失,如果已经登录,需要重新渲染路由。渲染的路由数据在登录时存在浏览器本地
**/
// if (sessionStorage.getItem('hasLogin')) {
// let sessionMenus = localStorage.getItem('menus')
// sessionMenus = sessionMenus ? JSON.parse(sessionMenus) : []
// let sessionRoutes = localStorage.getItem('userRoutes')
// RouterPlugin.install(router, store)
// sessionRoutes = sessionRoutes ? JSON.parse(sessionRoutes) : []
// router.$dynamicRoute.formatRoutes(sessionRoutes, true)
// store.dispatch('setUserRoutes', sessionRoutes)
// store.dispatch('setMenus', sessionMenus)
// }
// router.beforeEach((to, from, next) => {
// let hasLogin = sessionStorage.getItem('hasLogin')
// // console.log(to, from)
// if (to.name === from.name) {
// return
// }
// console.log(hasLogin)
// if (to.name === 'Login') {
// sessionStorage.clear()
// localStorage.clear()
// store.state.userRoutes = []
// store.state.menus = []
// next({ replace: true })
// resetRouter()
// return
// }
// if (!hasLogin) {
// next({ path: '/login', replace: true })
// return
// }
// next()
// })
/**
* 解决element-ui点击同一个菜单报错
* @type {VueRouter.push|*}
*/
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err);
};
export default router;
// 在使用的的地方调用
import router from './router/index';
new Vue({
router,
pinia,
render: h => h(App),
}).$mount('#app');
在登陆之后或者判断获取到用户信息之后重置路由
import { resetRouter } from './router/index';
import {cloneDeep} from 'lodash'
// menuList 为获取的菜单数据(树结构数据)
//重置路由
resetRouter();
this.$router.$dynamicRoute.formatRoutes(cloneDeep(menuList));