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 相关文章推荐
js 蒙版进度条(结合图片)
Mar 10 Javascript
jQuery 1.5 源码解读 面向中高阶JSER
Apr 05 Javascript
JS实现根据出生年月计算年龄
Jan 10 Javascript
jquery查找父元素、子元素(个人经验总结)
Apr 09 Javascript
调试JavaScript中正则表达式中遇到的问题
Jan 27 Javascript
基于jQuery实现网页打印功能
Dec 01 Javascript
js console.log打印对像与数组用法详解
Jan 21 Javascript
AngularJs学习第五篇从Controller控制器谈谈$scope作用域
Jun 08 Javascript
关于JSON.parse(),JSON.stringify(),jQuery.parseJSON()的用法
Jun 30 Javascript
随机生成10个不重复的0-100的数字(实例讲解)
Aug 16 Javascript
JavaScript寄生组合式继承原理与用法分析
Jan 11 Javascript
vue项目配置同一局域网可使用ip访问的操作
Oct 23 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
虫族 Zerg 魔法科技
2020/03/14 星际争霸
PHP获取数组中某元素的位置及array_keys函数应用
2013/01/29 PHP
js代码实现微博导航栏
2015/07/30 PHP
php如何实现不借助IDE快速定位行数或者方法定义的文件和位置
2017/01/17 PHP
php利用云片网实现短信验证码功能的示例代码
2017/11/18 PHP
php无限极分类实现方法分析
2019/07/04 PHP
ext读取两种结构的xml的代码
2008/11/05 Javascript
jquery checkbox实现单选小例
2013/11/27 Javascript
基于javascript、ajax、memcache和PHP实现的简易在线聊天室
2015/02/03 Javascript
Bootstrap fileinput文件上传组件使用详解
2017/06/06 Javascript
详解angularjs获取元素以及angular.element()用法
2017/07/25 Javascript
React Native悬浮按钮组件的示例代码
2018/04/05 Javascript
Vue中Quill富文本编辑器的使用教程
2018/09/21 Javascript
Javascript前端下载后台传来的文件流代码实例
2020/08/18 Javascript
再也不怕 JavaScript 报错了,怎么看怎么处理都在这儿
2020/12/09 Javascript
[03:48]大碗DOTA
2019/07/25 DOTA
python使用Pycharm创建一个Django项目
2018/03/05 Python
pandas把dataframe转成Series,改变列中值的类型方法
2018/04/10 Python
详解PyCharm配置Anaconda的艰难心路历程
2018/08/13 Python
一百行python代码将图片转成字符画
2021/02/19 Python
对Python捕获控制台输出流的方法详解
2019/01/07 Python
python实现图片插入文字
2019/11/26 Python
解决django xadmin主题不显示和只显示bootstrap2的问题
2020/03/30 Python
Python爬取微信小程序Charles实现过程图解
2020/09/29 Python
pandas处理csv文件的方法步骤
2020/10/16 Python
Python实现王者荣耀自动刷金币的完整步骤
2021/01/22 Python
matplotlib之pyplot模块之标题(title()和suptitle())
2021/02/22 Python
资生堂美国官网:Shiseido美国
2016/09/02 全球购物
实习生自我鉴定范文
2013/12/05 职场文书
幼师求职信
2014/06/23 职场文书
银行柜员与客户起冲突检讨书
2014/09/27 职场文书
索赔员岗位职责
2015/02/15 职场文书
西游降魔篇观后感
2015/06/15 职场文书
大学宣传委员竞选稿
2015/11/19 职场文书
Java基于字符界面的简易收银台
2021/06/26 Java/Android