前言:最近在掘金逛的时候,无意中看到前滴滴前端架构黄轶大佬,看到了大佬分享的一篇博客滴滴 webapp 5.0 Vue 2.0 重构经验分享 ,对于其中第5个问题(异步加载的业务线组件,如何动态注册?)的解决办法深为震撼。

  滴滴的首屏展示的同步业务线组件,对于一些业务线(比如顺风车,出租车,快车),这些业务线其实都可以成为单独spa应用,由于种种原因(我感觉组件化应该是很大的一个原因,构建包很小只打核心和初始化给用户显示的,剩下的业务线通过Vue异步组件注册引入)。Vue2提供的有异步注册组件

  我们注意到,官方提供的demo是异步引入本工程下的组件,对于滴滴(每个业务线是一个工程,在不同的git仓库存储)。滴滴的做法是将不同的业务线单独构建,构建的每个业务线是一个Vue实例(不知道这块是否理解有错,欢迎指正),然后将其传递给resolve函数(我感觉滴滴在这块的处理特别秒:比如全局的Vue,Vuex,公共业务组件的共享,异步业务组件的全局挂载,动态路由注册很是妙哉,希望大家去原地址查看,我这里就不赘述了)。下面是我自己的一个尝试:

  首先,在一个目录下运行 vue init webpack-simple async-component , 新建一个工程,用来开发需要异步注册的组件,在src下新建component目录,并创建index.js和async-component.vue文件,完整目录结构如下

  

  

// async-component.vue
<template>
<div class="async-component">
<h1 class="name">{{name}}</h1>
<div class="age">{{age}}</div>
</div>
</template> <script>
export default {
name: 'async-component',
data () {
return { }
},
props: {
name: {
type: String,
default: '张三'
},
age: {
type: Number,
default: 18
}
}
}
</script> <style lang="scss" scoped>
.async-component {
.name {
color: red;
}
.age {
color: green;
}
}
</style>
// index.js
/**
* Created by hs on 2019/7/15
*/
import AsyncComponent from './async-component'
if (typeof window !== 'undefined' && window.Vue) {
// 跟滴滴一样,将业务线异步组件存到window.modules下
window.modules = {
'async-component': AsyncComponent
}
}
// webpack.config.js 修改入口和出口文件
entry: process.NODE_ENV === 'development' ? './src/main.js' : './src/component/index.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'async-component.js'
},

  在 async-component 项目根目录运行 npm run build,然后dist生成了 async-component.js 文件,然后我们进入到dist文件夹下,运行 puer (一个web服务器,如果提示没有这个命令),用npm或者yarn全局安装下,puer启动后默认地址为 http://localhost:8000 , 在浏览器测试下http://localhost:8000/async-component.js , 能成功访问即可。然后启动下我的Vue测试项目,地址为 http://localhost:8080 ,Vue测试项目代码如下:

  

// App.vue
<template>
<div id="app">
<el-button type="primary" @click="changeComponent">加载异步组件</el-button>
<component :is="componentName" name="小明" :age="50"></component>
</div>
</template> <script>
export default {
name: 'App',
data() {
return {
};
},
methods: {
changeComponent () {
this.componentName = this.name
},
loadAsyncComponent () {
Vue.component(this.name, (resolve, reject) => {
this.loadScript('http://localhost:8000/async-component.js')
.then(() => {
resolve(window.modules['async-component'])
}).catch((e) => {
reject(e)
})
})
},
loadScript (url){
return new Promise((resolve, reject) => {
var script = document.createElement ("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
resolve()
}
};
} else { //Others
script.onload = function(){
console.log('complete')
resolve()
};
script.onerror = function (e) {
reject(e)
}
}
script.src = url;
document.getElementsByTagName("body")[0].appendChild(script);
})
}
},
mounted() {
this.loadAsyncComponent()
} }
</script> <style lang="scss">
* {
margin: 0;
padding: 0;
font-family: Microsoft YaHei;
}
#app {
background: #f1f1f5;
}
</style>

  浏览访问 http://localhost:8080,如下

 

点击按钮后如下

  

  个人感觉滴滴这个解决方法真的很精妙,但是细细想了一下,在公司的项目中好像用不到...这个方案是滴滴结合自身业务想出来的,技术还是要结合实际项目最好。最后引用下大佬对此相关的回复:滴滴这个场景是不适合用 webpack.ensure 的,因为是动态加载其它业务线的代码,压根代码就不在一个仓库下,只能通过 loadscript 方式加载,所以也有动态注册路由的需求。技术重构往往伴随着产品重构,单纯的技术重构不太现实,除非特别闲。。所以慢慢来吧,新项目可以用 vue2 了~

  

  

Vue动态注册异步组件(非同一个工程的组件)的更多相关文章

  1. vue 动态注册路由 require.context

    需求场景: 在日常的功能练习和调试过程中,需要一个demo项目进行功能测试,由于频繁.vue页面的同时,又要再router.js文件里面注册路由,感觉有点无聊和枯燥.基于此出发点,考虑能否自动读取文件 ...

  2. Vue动态加载异步组件

    背景: 目前我们项目都是按组件划分的,然后各个组件之间封装成产品.目前都是采用iframe直接嵌套页面.项目中我们还是会碰到一些通用的组件跟业务之间有通信,这种情况下iframe并不是最好的选择,if ...

  3. Vue - 动态组件 & 异步组件

    动态组件 <div id="app"> <components :is="com[2]"></components> < ...

  4. Vue 动态组件和异步组件

    基础案例 动态组件切换类比"bilibili-个人中心"的横向菜单切换不同的标签页的功能. 在Vue中可以使用 component 标签,并加一个特殊的属性(attribute) ...

  5. Vue动态组件

    前面的话 让多个组件使用同一个挂载点,并动态切换,这就是动态组件.本文将详细介绍Vue动态组件 概述 通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,可以实现动 ...

  6. 插件占坑,四大组件动态注册前奏(三) 系统BroadCast的注册发送流程

    转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52204143 前言:为什么要了解系统Activity,Service,BroadCas ...

  7. vue动态子组件的实现方式

    让多个组件使用同一个挂载点,并动态切换,这就是动态组件. 通过使用保留的 <component>元素,动态地绑定到它的 is 特性,可以实现动态组件. 方式一:局部注册所需组件 <d ...

  8. 插件占坑,四大组件动态注册前奏(二) 系统Service的启动流程

    转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52203903 前言:为什么要了解系统Activity,Service,BroadCas ...

  9. vue 动态组件

    动态组件 多个组件通过同一个挂载点进行组件的切换,is的值是哪个组件的名称,那么页面就会显示哪个组件 内置组件 (内置组件不会被渲染到页面上) component is属性     keep-aliv ...

随机推荐

  1. js数字每3位加一个逗号

    if(typeof val ==="number"){ var str = val.toString(); ? /(\d)(?=(\d{})+\.)/g : /(\d)(?=(?: ...

  2. POJ 1252 Euro Efficiency ( 完全背包变形 && 物品重量为负 )

    题意 : 给出 6 枚硬币的面值,然后要求求出对于 1~100 要用所给硬币凑出这 100 个面值且要求所用的硬币数都是最少的,问你最后使用硬币的平均个数以及对于单个面值所用硬币的最大数. 分析 :  ...

  3. Springboot-H2DB

    为什么在Springboot中用H2DB 用Springboot开发需要连接数据库的程序的时候,使用H2DB作为内存数据库可以很方便的调试程序. 怎么用 1.加入依赖 <dependency&g ...

  4. Oracle诊断:使用USER_SEGMENTS分配给表的物理空间大小

    假设我的SCHEMA的名字是abc, 需要知道在这个SCHEMA下的数据容量,可以通过下面的方式. 1.登录SCHEMA abc 2.使用USER_SEGMENTS查看SCHEMA abc数据容量 S ...

  5. fengmiantu3

  6. centos 6.x 安装配置 node.js 环境

    下载 可以在本地下载node.js最新版,然后通过ftp工具上传到服务器,或者直接在服务器终端使用wget命令下载(我当时下载的是node-v6.11.3-linux-x64版本,其他版本请查看上面链 ...

  7. 数位dp好题整理+自己wa过的细节记录

    花(fa)神的数论题 三倍经验:烦人的数学作业 windy数 手机号码 同类分布(博客先鸽着) 板子固然好,细节无限多. 花式wa题法,警示后来人. 1.手残害人不浅 (蒟蒻的我掉坑里不止一次) 2. ...

  8. ReentrantLock 源码分析

    ReentrantLock 1)ReentrantLock 类实现了和 synchronized 一样的内存语义,同时该类提供了更加灵活多样的可重入互斥锁定操作. 2)ReentrantLock 实例 ...

  9. accomplish、complete、finish、achieve和fulfill

    accomplish to succeed in doing something, especially after trying very hard vt. 完成:实现:达到 complete us ...

  10. Flask框架—flask_sqlalchemy组件使用

    一.flask_sqlalchemy组件 我们之前学过SQLAlchemy,一个独立的数据库关系对象映射,其实在flask中也有官方认可的第三方SQLAlchemy组件,用于处理flask中对象关系映 ...