在我们的 vue 项目中(特别是后台系统),总会出现一些需要多业务线共同开发同一个项目的场景,如果各业务团队向框架中提供一些私有的展示组件,但是这些组件并不能和框架一起打包,因为框架不能因为某个私有模块的频繁变更而重复构建发布。在这种场景下我们需要一个加载远程异步代码的组件来完成将这些组件加载到框架中。
vue-cli 作为 Vue 官方推荐的项目构建脚手架,它提供了开发过程中常用的,热重载,构建,调试,单元测试,代码检测等功能。我们本次的异步远端组件将基于 vue-cli 开发。
需求分析
- 如何加载远端的代码?
- 如何注册加载后的代码到框架中。
- 父组件如何和远端引入的组件通信。
- 远端代码如何复用框架中已引入的库。
- 避免因远端代码被类似 v-for 多次调用导致的不必要请求。
加载远端代码
远端代码应该存储在一个可访问的 URL 上,这样我们通过 Axios 类似的 HTTP client 请求这个链接拿到源码。
1 | import Axios from 'axios'; |
以上是基础代码 为了方便 一下例子中 我将省略重复的代码部分。
注册代码到框架中
这部分有些繁琐,涉及到多个问题:
- 浏览器并不支持
.vue
模板 或ES.next
语法,模块需要编译后才可以使用。
处理这部分比较简单,我们自己定义一个webpack配置文件来打包这些模板。
1 | // 在 build 目录下新建 webpack.sync-components.prod.conf.js 文件 |
至此我们的模块已经被编译成框架可以识别的文件。
- 如何将字符串转换成js对象。
new Function
。
1 |
|
- 转换后的js对象并不能被vue识别。
有两种可能会导致这个问题:
1 | // vue-loader v13 esModule 更新 默认值为 true, v12及之前版本为 false, 此项配置影响 vue 自身异步组件写法以及 webpack 打包结果 |
至此 远程组件就被引入到框架中了。
父组件如何和远端引入的组件通信
这里有一个问题,从 view组件
到 远程异步加载组件
再到 实际业务组件
通信一共三层,中间层 远程异步组件
作为公共组件不可被修改,需要 view组件
直接向 实际业务组件
通信。vuex 和 eventBus 方案都过于繁琐,这里我们采用 $attrs 和 $listeners(vue v2.4+), 来实现 “fallthrough”(vue组件跨层级通信)。
1 | // 修改 sync-component.vue 组件 |
远端代码如何复用框架中已引入的库
我们不希望看到远端组件和框架中存在较大库或插件的重复的引入,这部分内容尚处在实践阶段,主要思路是把公共库挂载到Vue原型链上实现组件公共复用 Vue.prototype.$xxx
。
1 | // 全局添加 axios 对象 |
引入的远程组件可以访问到框架中的公共包了,这时候还需要配置 webpack 使远程组件打包时不要包含公共包的代码。
1 | // webpack.sync-components.prod.conf.js 添加 |
避免因远端代码被类似 v-for 多次调用导致的不必要请求。
这部分我们直接用一个全局变量做字典,存储 以 请求地址:数据
为子项的数组。
1 | async mounted() { |
至此,异步远程组件就可以加载并和框架进行通信了。
本文中的源码请访问 github 获取,组件已经发布到 NPM 上,可以直接安装。
拓展阅读:
如何在 npm 上发布你的 vue 组件