這篇文章是基於 vue-router v4.02 版本來實現的。vue-router v4.0.2 的版本與 v.3.x 的版本區別有很多,可以直查看一下這裏, 本片文章只說一下怎麼使用vue-router去動態創建路由。具體可以直接看代碼,一目瞭然了。
使用vue-cli3創建項目
vue create router-test
設置路由 "router/index.js"
import { createRouter, createWebHashHistory } from 'vue-router'
import defaultRouter from './defaultRouter'
import store from '@/store'
import dynamicRouter from './dynamicRouter'
const router = createRouter({
history: createWebHashHistory(),
routes: defaultRouter,
scrollBehavior(to, from, savedPosition) {
// keep-alive 返回緩存頁面後記錄瀏覽位置
if (savedPosition && to.meta.keepAlive) {
return savedPosition;
}
// 異步滾動操作
return new Promise((resolve) => {
setTimeout(() => {
resolve({ x: 0, y: 0 })
}, 200)
})
}
})
// 重新添加路由並消除路由重複警告
const selfaddRoutes = function(params) {
params.forEach(item => router.addRoute(item))
}
router.beforeResolve(async (to, from, next) => {
let { hasRoute } = store.state; //防止路由重複添加
if (hasRoute) {
next();
} else {
await dynamicRouter(selfaddRoutes)
let routes = router.getRoutes(); //重新設置跳轉路由
routes.forEach((item) => {
if (to.path == item.path) {
to.name = item.name;
}
})
next({ ...to, replace: true })
}
})
export default router
- v4版本去掉了
addRoutes()
方法,現用addRoute()
,所有路由只能一個一個添加; - 默認路由處添加了
/:pathMatch(.*)*
全路由匹配,在首次(刷新)導航進入到一個動態路由地址,這時會直接跳到 page_error 頁面, 所以在導航進入動態路由地址時需要重新將to
與最新的路由列表進行匹配,這裏直接更改to.name
值,即可;
使用vuex設置路由狀態 "store/index.js"
import { createStore } from 'vuex'
export default createStore({
state: {
"hasRoute": false
},
metters:{
"hasRoute" : state => state.hasRoute
},
mutations: {
setHasRoute(state, hasRoute){
state.hasRoute = hasRoute;
}
},
actions: {},
modules: {}
})
設置默認路由 "router/defaultRouter.js"
import Home from '@/views/Home.vue'
const defaultRouter = [{
path: '',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('@/views/About.vue')
}, {
path: '/:pathMatch(.*)*',
name: "page_error",
component: () => import('@/views/error_page/404'),
meta: {
requiresAuth: false
}
}
]
export default defaultRouter
設置動態路由 "router/dynamicRouter.js"
import store from '@/store'
import defaultRouter from './defaultRouter'
import axios from 'axios';
//重新構建路由對象
let menuMap = function(menu) {
return menu.map(v => {
let { path, name, component, title, icon = "" } = v;
let item = {
path,
name,
meta: {
title,
icon
},
component: () => import(`@/${component}`)
};
if (v.children) {
item.children = menuMap(v.children);
}
return item;
})
}
//異步獲取路由列表
const addPostRouter = function(selfaddroutes) {
return new Promise((resolve, reject) => {
axios({
url: './static/menu.json'
}).then((res) => {
defaultRouter.unshift(...menuMap(res.data));
selfaddroutes(defaultRouter);
store.commit('setHasRoute', true); //更新路由狀態;
resolve(true)
}).catch((err) => {
reject(err);
})
})
}
export default addPostRouter;
menu.json
該文件路徑地址爲 "public/static/menu.json"
[{
"path": "/add",
"name": "add",
"title": "添加用戶",
"component": "views/user/add"
},
{
"path": "/list",
"name": "list",
"title": "用戶列表",
"component": "views/user/list"
},
{
"path": "/task",
"name": "task",
"title": "任務",
"component": "views/task/index",
"children": [
{
"path": "list",
"name": "task_list",
"title": "任務列表",
"component": "views/task/list"
},
{
"path": "add",
"name": "task_add",
"title": "添加任務",
"component": "views/task/add"
}]
}]
刪除路由
router.addRoute({ path: '/about', name: 'about', component: About })
// remove the route
router.removeRoute('about')