项目场景:
将项目静态路由替换成动态路由,通过后台数据拿到路由配置信息动态加载
问题描述:
小编将路由信息与系统菜单信息存在一起,当登录后拿到菜单信息后同时处理路由数据,过程肯定不是那么一帆风顺的,下面是导致失败的重点
错误示例
let func = function(list) {if (list && list.length > 0) {for (let ind = list.length - 1; ind >= 0; ind--) {if (list[ind].children && list[ind].children.length > 0) {func(list[ind].children);if (list[ind].children.length === 0) {delete list[ind].children;}}if (list[ind].permission) {permissionList.push(list[ind].permission);}if (list[ind].href) {menuUrlList.push(list[ind].href);}if (list[ind].href && list[ind].isShow && list[ind].components) {routerList.push({path: list[ind].href,redirect: list[ind].redirect || null,component: () => import(list[ind].components),meta: { title: list[ind].name }});}if (list[ind].isShow === '0') {list.splice(ind, 1);}}}return list;};
这是处理菜单数据的完整代码,咱们只关注处理路由数据这一段
if (list[ind].href && list[ind].isShow && list[ind].components) {routerList.push({path: list[ind].href,redirect: list[ind].redirect || null,component: () => import(list[ind].components),meta: { title: list[ind].name }});}
首先小编这边用了import方式用于组件的懒加载,经过多次尝试未果,然后进行了第二次改造
if (list[ind].href && list[ind].isShow && list[ind].components) {routerList.push({path: list[ind].href,redirect: list[ind].redirect || null,component: resolve => require([list[ind].components],resolve),meta: { title: list[ind].name }});}
第二次依然挂逼,这里思来想去没啥毛病,但就是没办法加载到组件,中途来来回回折腾了n次,发现require([‘@/components/page/xxxx’],resolve)这个明文方式奏效,这里证明require是可以的
然后小编去gitee上看了下人家的源代码,逻辑上没毛病,发现了一个细节,于是又改造
if (list[ind].href && list[ind].isShow && list[ind].components) {routerList.push({path: list[ind].href,redirect: list[ind].redirect || null,component: resolve => require([`@/components/${list[ind].components}`],resolve),meta: { title: list[ind].name }});}
可以看到我把@/component当成明文写在外边,后台传的数据改造了一下,只传后半部分,这样是完全ok的
原因分析:
1、通过这次问题主要了解到,webpack打包通过找到别名去编译路径,如果别名放在后台数据里,编译时并没有这些数据,编译后通过请求数据拿到别名无法进行二次编译,这也是失败的主要原因
2、成功以后尝试用import代提require,发现不行,大致是因为import为ES语法,具体原因未深究
解决方案:
不仅是动态路由中用到,所有涉及用动态数据进行懒加载组件的都适用
component: resolve => require([`@/components/${list[ind].components}`],resolve)
所有带别名的部分都不可从后台数据中获取,必须将别名写死,才能在webpack打包时进行编译