手写路由有点坑,特别是刚接触路由的朋友。分享一个自动初始化路由的方法(需要cli3+)。首先,路径大致是这样放的。我们的目的是让路由自动注册pages目录下的文件。注册地址默认为./pages/下文件的相对地址。以此为例,大概是这样的:importindexfrom'@/pages/index.vue'importhome_homefrom'@/pages/home/home.vue'//应该有一个@/pages/home.vue文件.这只是演示,我偷懒routes:[{path:'/index',component:index,name:'index'},{path:'/home/',children:[{path:'/home/home',component:home_home,name:'home_home'}]}]自动加载路由,首先让脚手架自动读取文件,使用的核心api是require.context,只有cli3+支持;直接在下面的代码//./router.jsimportVuefrom'vue'importRouterfrom'vue-router'constroutesMap=newMap(),pageList=require.context('./',//指定搜索路径forfilestrue,//是否继续搜索子路径/^(\.\/pages).*(\.vue)$///定期过滤文件名,这里查找下所有'.vue'文件'./pages/'目录),//此处返回方法集合turnArr=(mapArr)=>{returnArray.from(mapArr.values()).map((i)=>{i.children&&(i.children=turnArr(i.children))returni})};//声明一个将Map转换为数组的方法。后面遍历转换需要Array.from(pageList.keys())//pageList.keys返回所有匹配的文件paths.map(i=>[i,...i.replace(/^(\.\/pages\/)/,'').replace(/(\.vue)$/,'').split('/')])。sort((a,b)=>a.length-b.length).forEach((pathArr)=>{//pageList(filepath)返回指定文件export的内容,这里默认当然是exportdefault的内容=>ourcomponentletcomponent=pageList(pathArr.shift()).default,defaultName=pathArr.join('_'),tarName=pathArr.pop(),childrenArr=pathArr.reduce((re,i)=>{if(!re.get(i)){//eslint-disable-next-lineconsole.warn('地址%s没有指定控件',i)//父路由同名有子路由是合理的,但你也可以不合理re.set(i,{path:`/${i}/`})}if(!re.get(i).children){re.get(i).children=newMap()}returnre.get(i).children},routesMap);//这里初始化页面路由配置,vue文件下的_route会浅覆盖默认配置childrenArr.set(tarName,Object.assign({name:defaultName,component,path:`/${[...pathArr,tarName].join('/')}`},component._route||{}))})//这里考虑了子路由的嵌套,所以使用Map对象(查找上层路由当深度嵌套子路由时)Vue.use(Router)constrouter=newRouter({mode:'history',routes:turnArr(routesMap),//路由可以接收Map对象,子路由不能接收Map对象。所以还是需要全部转成数组形式})exportdefaultrouter这样基本上就不用再写路由了,路由的嵌套直接通过文件路径解析。例如,一个foo和boo子路由应该嵌套在index下。直接创建一个同名的文件夹index,将foo和boo放在index文件夹中。上面提到vue文件下的_route对象会覆盖默认配置,我们可以通过这种方式添加重定向。//redirect.vue可以直接放在pages目录或者重写默认配置当然这个需要.contextAPI还可以做其他的事情,比如自动全局注册组件(vue官方文档),比如自动帮你加载js模块,就不一一介绍了,请各位大佬自行研究。关于自动初始化路由的问题,如果大家有什么意见或者建议,欢迎指出和讨论。?(′???`)
