因为 Vue Router 支持 嵌套路由,所以愉快的写起了相对路径。
const router = new VueRouter({
routes: [
{ path: '/user', component: User,
children: [
{
// 当 /user/profile 匹配成功,
// UserProfile 会被渲染在 User 的 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/posts 匹配成功
// UserPosts 会被渲染在 User 的 中
path: 'posts',
component: UserPosts
}
]
}
]
})
一时相对一时爽,可是此时非彼时。
想要根据 routes
渲染菜单,菜单就需要路由跳转,而我又没有写 name
命名路由,故如下跳转不可行:
this.$router.push({ name: 'user' })
可是 this.$router.options.routes
这货也拿不到绝对路径 path
,故如下跳转也不可行:
this.$router.push({ path: '/user' })
何解
此解有三:
- 老老实实写绝对路径呗
- 或者全部上命名路由
- 或者路由转换成绝对路径
写绝对内心有点抵触,命名亦是个头疼的事情,那...
把拿到 this.$router.options.routes
的数据进行重组呗
解
- 路径转换(仅针对对 Vue Router 的路径,不考虑 node 那种 path.resolve):
function resolvePath(...paths) {
let i = paths.length
// 反向查找 / 开头的路径
while (--i) {
if (/^\//.test(paths[i])) break
}
return paths.slice(i)
.join('/') // 加入 '/'
.replace('//', '/') // 替换可能存在的 '//'
}
- 测试:
resolvePath('/', 'a', 'cb', '/www/', 'c') // "/www/c"
resolvePath('/', 'a', 'cb', 'www', 'c') // "/a/cb/www/c"
完整实例
假设路由:
const routes = [
{
"path": "/",
"meta": {
"name": "首页"
},
"children": [
{
"path": "",
"redirect": "/dashboard"
},
{
"path": "/dashboard",
"name": "dashboard",
"meta": {
"name": "Dashboard"
}
},
{
"path": "user",
"meta": {
"name": "用户管理"
},
"children": [
{
"path": "list",
"meta": {
"name": "列表"
}
},
{
"path": "edit",
"meta": {
"name": "编辑/创建"
}
},
{
"path": "log",
"meta": {
"name": "日志"
}
}
]
}
]
},
{
"path": "/auth",
"name": "auth"
}
]
转换函数:
function resolvePath ( ...paths ) {
let i = paths.length
while ( --i ) {
if ( /^\//.test( paths[i] ) ) break
}
return paths.slice( i )
.join( '/' ) // 加入 '/'
.replace( '//', '/' ) // 替换可能存在的 '//'
}
function restructure ( routes = [], base = '/' ) {
return routes.map( route => {
let { path, children = [] } = route
path = resolvePath( base, path )
if ( children.length > 0 ) {
route.children = restructure( children, path )
}
return {
...route,
path
}
} )
}
export default restructure
测试:
// 假设 this.$router.options = '/'
const result = restructure (routes, '/')
console.log( JSON.stringify(result, null, 4) )
// 输出
[
{
"path": "/",
"meta": {
"name": "首页"
},
"children": [
{
"path": "/",
"redirect": "/dashboard"
},
{
"path": "/dashboard",
"name": "dashboard",
"meta": {
"name": "Dashboard"
}
},
{
"path": "/user",
"meta": {
"name": "用户管理"
},
"children": [
{
"path": "/user/list",
"meta": {
"name": "列表"
}
},
{
"path": "/user/edit",
"meta": {
"name": "编辑/创建"
}
},
{
"path": "/user/log",
"meta": {
"name": "日志"
}
}
]
}
]
},
{
"path": "/auth",
"name": "auth"
}
]
---- Vinci, Sunday, September 29 2019, Sunny