Vue动态组件和异步组件原理详解


Posted in Javascript onMay 06, 2019

前言

在vue官方资料中,我们可以可以很学会如何通过vue构建“动态组件”以及“异步组件”,然而,在官方资料中,并没有涉及到真正的“动态异步”组件,经过大量的时间研究和技术分析,我们给出目前比较合理的技术实现方式,并分析一下vue动态异步组件的原理

动态组件 & 异步组件的存在,使得我们更方便地控制首屏代码的体积,加快加载速度。

抛开具体细节不谈,一个普通 Vue 组件从创建到展现在页面里,主要经历了以下流程:

// 组件 Object
{
 template: '<div>I am async!</div>'
}
// 经过 compileToFunctions 得到对应的 render function 
with(this) {
 return _c('div', [_v("I am async!")])
}
// 在经过 render 得到 Vnode 再 update 成为真实DOM

动态组件&异步组件与之有什么区别呢?

主要区别在于 render 中 createComponent 这一步,举例。

// 组件
Vue.component('example', {
 template: '<div>I am async!</div>'
})

普通组件在 createComponent 时,会依据开发者自定义的 options,利用 Vue.extend 生成对应的构造函数,从而得到对应的 Vnode 。而一个异步组件

// 异步组件
Vue.component('async-example', function (resolve, reject) {
 // 利用 setTimeout 模拟请求
 setTimeout(function () {
  // 向 `resolve` 回调传递组件定义
  resolve({
   template: '<div>I am async!</div>'
  })
 }, 1000)
})

则是要经过一系列处理,具体过程如下

在源码的 create-component。

// async component
let asyncFactory
if (isUndef(Ctor.cid)) {
 asyncFactory = Ctor
 Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context)
 if (Ctor === undefined) {
  // return a placeholder node for async component, which is rendered
  // as a comment node but preserves all the raw information for the node.
  // the information will be used for async server-rendering and hydration.
  return createAsyncPlaceholder(
   asyncFactory,
   data,
   context,
   children,
   tag
  )
 }
}

首先 Ctor 就与之前不同,这里为一个 function

function (resolve, reject) {
 // 利用 setTimeout 模拟请求
 setTimeout(function () {
  // 向 `resolve` 回调传递组件定义
  resolve({
   template: '<div>I am async!</div>'
  })
 }, 1000)
}

之后调用 resolveAsyncComponent(asyncFactory, baseCtor, context)

resolveAsyncComponent 在源码的 resolveAsyncComponent。

resolveAsyncComponent 的主要功能是定义 Ctor 所需要的 resolve 、reject 函数

// factory 为 Ctor
factory(resolve, reject)

以 resolve 函数为例

const resolve = once((res: Object | Class<Component>) => {
 // 缓存 resolved
 factory.resolved = ensureCtor(res, baseCtor)
 // 强制渲染
 if (!sync) {
 	forceRender(true)
 }
})

once 字面理解,就是只调用一次。当 Ctor 中 setTimeout 结束时调用。

ensureCtor 就是 Vue.extend 的封装以适应不同场景,所以 resolve 函数的主要功能就是在异步完成时,将得到的 Ctor 转化为构造函数,缓存在 factory.resolved 中。

之后利用 forceRender(true) 强制重新 render,由于之前缓存了 factory.resolved,resolveAsyncComponent 函数就直接返回了组件的构造函数。

if (isDef(factory.resolved)) {
 return factory.resolved
}

之后就与普通组件一致了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
制作特殊字的脚本
Jun 26 Javascript
javascript编程起步(第七课)
Jan 10 Javascript
侧栏跟随滚动的简单实现代码
Mar 18 Javascript
jquery validation验证身份证号,护照,电话号码,email(实例代码)
Nov 06 Javascript
文本域中换行符的替换示例
Mar 04 Javascript
jQuery中bind()方法用法实例
Jan 19 Javascript
jQuery解析XML文件同时动态增加js文件的方法
Jun 01 Javascript
JS实现随页面滚动显示/隐藏窗口固定位置元素
Feb 26 Javascript
详解vue.js数据传递以及数据分发slot
Jan 20 Javascript
Vue项目使用localStorage+Vuex保存用户登录信息
May 27 Javascript
Elasticsearch实现复合查询高亮结果功能
Sep 10 Javascript
使用Canvas绘制一个游戏人物属性图
Mar 25 Javascript
微信小程序按钮点击跳转页面详解
May 06 #Javascript
详解vue中移动端自适应方案
May 05 #Javascript
解决ie11 SCRIPT5011:不能执行已释放Script的代码问题
May 05 #Javascript
彻底揭秘keep-alive原理(小结)
May 05 #Javascript
angular4+百分比进度显示插件用法示例
May 05 #Javascript
vuejs数据超出单行显示更多,点击展开剩余数据实例
May 05 #Javascript
Vue+Express实现登录状态权限验证的示例代码
May 05 #Javascript
You might like
PHP中的session永不过期的解决思路及实现方法分享
2011/04/20 PHP
php异常处理技术,顶级异常处理器
2012/06/13 PHP
php和javascript之间变量的传递实现代码
2012/12/19 PHP
PHP数组内存利用率低和弱类型详细解读
2017/08/10 PHP
解决laravel中日志权限莫名变成了root的问题
2019/10/17 PHP
PHP代码覆盖率统计详解
2020/07/22 PHP
仿迅雷焦点广告效果(JQuery版)
2008/11/19 Javascript
javascript用户注册提示效果的简单实例
2013/08/17 Javascript
用原生JS获取CLASS对象(很简单实用)
2014/10/15 Javascript
JavaScript实现自动变换表格边框颜色
2015/05/08 Javascript
JavaScript的removeChild()函数用法详解
2015/12/27 Javascript
js微信分享API
2020/10/11 Javascript
AngularJS表单详解及示例代码
2016/08/17 Javascript
JS/jquery实现一个网页内同时调用多个倒计时的方法
2017/04/27 jQuery
JavaScript实现反转字符串的方法详解
2017/04/27 Javascript
浅谈JS封闭函数、闭包、内置对象
2017/07/18 Javascript
使用travis-ci如何持续部署node.js应用详解
2017/07/30 Javascript
JS防抖和节流实例解析
2019/09/24 Javascript
JS手写一个自定义Promise操作示例
2020/03/16 Javascript
vue 输入电话号码自动按3-4-4分割功能的实现代码
2020/04/30 Javascript
vue 使用lodash实现对象数组深拷贝操作
2020/09/10 Javascript
通过源码分析Python中的切片赋值
2017/05/08 Python
Python编程实现两个文件夹里文件的对比功能示例【包含内容的对比】
2017/06/20 Python
python使用super()出现错误解决办法
2017/08/14 Python
python实现八大排序算法(1)
2017/09/14 Python
Python实现串口通信(pyserial)过程解析
2019/09/25 Python
深入浅析pycharm中 Make available to all projects的含义
2020/09/15 Python
html5触摸事件判断滑动方向的实现
2018/06/05 HTML / CSS
宿舍卫生检讨书
2014/01/16 职场文书
劳动竞赛活动方案
2014/02/20 职场文书
社区巾帼文明岗事迹材料
2014/06/03 职场文书
幼儿教师辞职信
2015/02/27 职场文书
员工升职自荐信
2015/03/27 职场文书
2015年中学总务处工作总结
2015/07/22 职场文书
Golang 如何实现函数的任意类型传参
2021/04/29 Golang
CentOS7安装GlusterFS集群以及相关配置
2022/04/12 Servers