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 相关文章推荐
Dojo 学习要点
Sep 03 Javascript
jquery1.5.1中根据元素ID获取元素对象的代码
Apr 02 Javascript
jquery 卷帘效果实现代码(不同方向)
Feb 05 Javascript
sogou地图API用法实例教程
Sep 11 Javascript
限制上传文件大小和格式的jQuery插件实例
Jan 24 Javascript
Jquery循环截取字符串的方法(多出的字符串处理成&quot;...&quot;)
Nov 28 Javascript
jQuery UI实现动画效果代码分享
Aug 19 jQuery
Makefile/cmake/node-gyp中区分判断不同平台的方法
Dec 18 Javascript
Vue执行方法,方法获取data值,设置data值,方法传值操作
Aug 05 Javascript
Vue axios 跨域请求无法带上cookie的解决
Sep 08 Javascript
详解VUE中的插值( Interpolation)语法
Oct 18 Javascript
vue自定义右键菜单之全局实现
Apr 09 Vue.js
微信小程序按钮点击跳转页面详解
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
全国FM电台频率大全 - 23 四川省
2020/03/11 无线电
PHP 双链表(SplDoublyLinkedList)简介和使用实例
2015/05/12 PHP
php数组函数array_key_exists()小结
2015/12/10 PHP
Laravel框架实现多数据库连接操作详解
2019/07/12 PHP
php设计模式之观察者模式定义与用法经典示例
2019/09/19 PHP
JavaScript 学习笔记(十三)Dom创建表格
2010/01/21 Javascript
提取字符串中年月日的函数代码
2013/11/05 Javascript
深入理解javascript中defer的作用
2013/12/11 Javascript
jQuery原生的动画效果
2015/07/10 Javascript
JS实现的车标图片提示效果代码
2015/10/10 Javascript
jQuery实现的导航下拉菜单效果示例
2016/09/05 Javascript
微信小程序 首页制作简单实例
2017/04/07 Javascript
深入理解JavaScript创建对象的多种方式以及优缺点
2017/06/01 Javascript
jquery手机触屏滑动拼音字母城市选择器的实例代码
2017/12/11 jQuery
express+mockjs实现模拟后台数据发送功能
2018/01/07 Javascript
浅谈FastClick 填坑及源码解析
2018/03/02 Javascript
layui多iframe页面控制定时器运行的方法
2019/09/05 Javascript
vue路由传参页面刷新参数丢失问题解决方案
2019/10/08 Javascript
Js生成随机数/随机字符串的方法小结【5种方法】
2020/05/27 Javascript
微信小程序实现上传照片代码实例解析
2020/08/04 Javascript
[02:54]DOTA2英雄基础教程 暗影牧师戴泽
2013/12/05 DOTA
Python转换HTML到Text纯文本的方法
2015/01/15 Python
Python中用PIL库批量给图片加上序号的教程
2015/05/06 Python
详解python的四种内置数据结构
2019/03/19 Python
python GUI库图形界面开发之PyQt5工具栏控件QToolBar的详细使用方法与实例
2020/02/28 Python
解决IDEA 的 plugins 搜不到任何的插件问题
2020/05/04 Python
python 第三方库paramiko的常用方式
2021/02/20 Python
药物学专业学生的自我评价
2013/10/27 职场文书
我们的节日春节活动方案
2014/08/22 职场文书
政协会议宣传标语
2014/10/09 职场文书
写给孩子的新学期寄语
2015/02/27 职场文书
2016道德模范先进事迹材料
2016/02/26 职场文书
Python合并多张图片成PDF
2021/06/09 Python
Java实战之用Swing实现通讯录管理系统
2021/06/13 Java/Android
MySQL中的引号和反引号的区别与用法详解
2021/10/24 MySQL
nginx常用配置conf的示例代码详解
2022/03/21 Servers