需求:当我vue-routes配置的时候,嫌弃require(‘’)引入的路径太长,想用变量替换他,为了美观,也没了精简代码。
当你在开发一个大型单页面应用的时候,项目之初一般做法是所有的路由规则都维护在一个route.js的文件里。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| const router = new VueRouter({ routes: routes }) // routes.js const routes = { path: 'usermanage', component: require('page/systemManagement/usermanage/usermanage.vue'), children: [ { path: 'student_manage', component: r => require.ensure([], () => r(require('page/systemManagement/usermanage/usermanage.student_manage.vue'))) }, { path: 'user_audit', component: r => require.ensure([], () => r(require('page/systemManagement/usermanage/usermanage.user_audit.vue'))) }, { path: 'role_permission', component: r => require.ensure([], () => r(require('page/systemManagement/usermanage/usermanage.role_permission.vue'))) }, { path: 'role_assign', component: r => require.ensure([], () => r(require('page/systemManagement/usermanage/usermanage.role_assign.vue'))) }, { path: 'class_manage', component: r => require.ensure([], () => r(require('page/systemManagement/usermanage/usermanage.class_manage.vue'))) } ] };
|
这里的require.ensure上一篇文章 webpack.ensure介绍了:webpack的语法,实现按需加载的。
随着业务代码的增长路由很快边长,看起来乱糟糟(怪我强迫症患了):
刚开始发现路径太长,用一个变量替换,还用es6语法:
const user_path = `page/systemManagement/usermanage/`;
上边的component改为了:
`component:r=>(require(`${user_path}usermanage.vue`))`
报错了,刚开始以为是es6语法写错了,改成字符串的写法,还是报错,我就觉得这不应该了,一个念头飘过,require不支持变量的写法,baidu,google…… oh,小样,果然如此,node不支持,不过也发现了另外一个好东西,require.context。
简单说下context()的用法:官网地址
require的context方法
你还可以使用 require.context() 方法来创建自己的上下文(模块)。
你可以给这个方法传3个参数:要搜索的文件夹目录,是否还应该搜索它的子目录,一个匹配文件的正则表达式。
webpack会在构建的时候解析代码中的 require.context() 。
语法如下:
require.context(directory, useSubdirectories = false, regExp = /^\.\//)
示例:
require.context("./test", false, /\.test\.js$/);
// (你创建了)一个test文件夹下面(不包含子目录),能被require请求到,所有文件名以 `.test.js` 结尾的文件形成的上下文(模块)。
require.context("../", true, /\.stories\.js$/);
// (你创建了)一个父级文件夹下面(包含子目录),所有文件名以 `.stories.js` 结尾的文件形成的上下文(模块)。
上下文模块 API
一个上下文模块导出一个(require)方法,这个方法可以接收一个参数:请求的对象。 A context module exports a (require) function that takes one argument: the request.
导出的方法有3个属性: resolve, keys, id。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| resolve 是一个函数,它返回所请求的对象被解析后得到的模块id。
keys 也是一个函数,它返回一个数组,由所有可能被上下文模块处理的请求的对象(译者注:参考下面第二段代码中的key)组成。
比如,在你想引入一个文件夹下面的所有文件,或者引入能匹配正则表达式的文件,你可以这样:
function importAll (r) { r.keys().forEach(r); } importAll(require.context('../components/', true, /\.js$/));
var cache = {}; function importAll (r) { r.keys().forEach(key => cache[key] = r(key)); } importAll(require.context('../components/', true, /\.js$/)); // 在构建时,所有被require的模块都会被存到(上面代码中的)cache里面。
|
借鉴了网上内容 传送门
但是直接引用到vue-route里边还是有问题的,你还需要像上边提到的例子中,有多少子路由,还得在子页面中引入自己相关的路由,所以,为了一个文件就搞定的事,我开始了漫长且兴奋的研究。
ok,过程的尝试和研究就不细说了,直接上代码。当然,你也可以先自己研究,实在出不来,再查看我的代码,毕竟,你可以很清楚的明白他的实现过程。
1 2 3 4 5 6 7 8 9 10
| { path: 'usermanage', component: r => require.ensure([], () => r(require('page/systemManagement/usermanage/usermanage.vue'))), children: (r => { return r.keys().map(key => {return { path: key.split('.')[2], component: r(key) }}); })(require.context('page/systemManagement/usermanage/',false,/usermanage\.\w+\.vue$/)), }
|
上例中的path 自己可以适当的改下,用正则都行。
不过遗憾的是,require.comtext()中第一个参数,依旧只能写字符串路径。其实,这个才是我要解决的问题。到最后也是没有解决。
不过还好学到了另外的知识,分享出来。
ok,这么高大上的东西,留在项目中,让参与项目的人颤抖吧。开玩笑啦,大家一起学习,一起进步。