/**
* 根据 pages 目录自动添加路由
* 参考 nuxt https://zh.nuxtjs.org/guide/routing
*/
import Vue from 'vue'
import Router, { Route } from 'vue-router'
import { interopDefault } from './util'
import OfflineRedirect from './hooks/offline'
import disposer from '@/utils/disposer'
Vue.use(Router)
interface RouteType {
path:string,
[key:string]:any
}
const context = require.context('../pages', true, /\.vue$/, 'lazy')
/**
* 根据页面的路径 设置路由的path
* @param page /Home/Index => path: /home
* /Home/Once => path: /home/once
* @param prefix
*/
function getPath(pages:string[], prefix = '/') {
const [first, second = ''] = pages
const firstPath = first.toLocaleLowerCase()
const secondPath = second.toLocaleLowerCase()
if (firstPath === 'index') {
return prefix
}
if (secondPath.startsWith('_')) {
return `${prefix}${firstPath}:${secondPath.slice(1)}`
}
if (secondPath === 'index' || secondPath === '') {
return `${prefix}${firstPath}`
}
return `${prefix}${firstPath}/${secondPath}`
}
/**
* 给路由设置 component 属性
* 懒加载组件
* @param route
* @param path
*/
function importComponent(route:RouteType, pathKeys:string[]) {
const path = pathKeys.join('/')
route.component = () => interopDefault(import(`@/pages/${path}.vue`))
}
/**
* 设置子路由
* @param r
*/
function getChildrens(route:RouteType, pathKeys:string[]) {
const [, pageName] = pathKeys
const path = pageName.toLocaleLowerCase()
if (!route.children) {
route.children = []
}
const childRoute:RouteType = {
path: ''
}
importComponent(childRoute, pathKeys)
if (path !== 'index') {
childRoute.path = path
childRoute.name = pathKeys.join('')
} else {
childRoute.name = route.name
delete route.name
}
route.children.push(childRoute)
}
const paths = context
.keys()
.map(v => v.replace(/\.(\/|vue)/g, '').split('/'))
const reverseKeys = paths.sort((a, b) => a.length - b.length)
// const pathProxies:Record<string, RouteType> = {}
const onePages = reverseKeys.filter(v => v.length === 1)
.reduce((current, next) => current.concat(next), [])
const pathProxies:Record<string, RouteType> = {}
reverseKeys.forEach((pathKeys) => {
const key = getPath(pathKeys)
const [firstPath] = pathKeys
if (onePages.indexOf(firstPath) > -1 && pathKeys.length === 2) {
const route = pathProxies[getPath([firstPath])]
getChildrens(route, pathKeys)
} else {
pathProxies[key] = {
path: key,
name: pathKeys.join('')
}
importComponent(pathProxies[key], pathKeys)
}
})
const routes = Object.values(pathProxies)
const base = `${process.env.PREFIX}/`
const router = new Router({
base,
mode: 'history',
scrollBehavior(to:Route, from:Route) {
return { x: 0, y: 0 }
},
routes
})
router.beforeEach(OfflineRedirect)
router.afterEach(() => {
disposer.dispose()
})
router.onError((error) => {
const pattern = /Loading chunk chunk-(\w)+ failed/g
const isChunkLoadFailed = pattern.test(error.message)
const targetPath = (router as any).history.pending.fullPath
if (isChunkLoadFailed) {
router.replace(targetPath)
}
})
export default router
网友评论