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控件
May 07 Javascript
chrome浏览器不支持onmouseleave事件的解决技巧
May 31 Javascript
JS连连看源码完美注释版(推荐)
Dec 09 Javascript
JavaScript使用pop方法移除数组最后一个元素用法实例
Apr 06 Javascript
JavaScript中的lastIndexOf()方法使用详解
Jun 06 Javascript
原生js实现可拖动的登录框效果
Jan 21 Javascript
js基于FileSaver.js 浏览器导出Excel文件的示例
Aug 15 Javascript
Angular实现双向折叠列表组件的示例代码
Nov 21 Javascript
ionic2中使用自动生成器的方法
Mar 04 Javascript
如何自动化部署项目?折腾服务器之旅~
Apr 16 Javascript
Vue中的循环及修改差值表达式的方法
Aug 29 Javascript
js判断密码强度的方法
Mar 18 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
杏林同学录(六)
2006/10/09 PHP
php下将XML转换为数组
2010/01/01 PHP
QueryPath PHP 中的jQuery
2010/04/11 PHP
PHP调用Linux的命令行执行文件压缩命令
2013/01/27 PHP
php中Socket创建与监听实现方法
2015/01/05 PHP
PHP基于PDO调用sqlserver存储过程通用方法【基于Yii框架】
2017/10/07 PHP
php封装的page分页类完整实例代码
2020/02/01 PHP
非常漂亮的JS代码经典广告
2007/10/21 Javascript
Javascript的闭包
2009/12/31 Javascript
jquery jqPlot API 中文使用教程(非常强大的图表工具)
2011/08/15 Javascript
js修改table中Td的值(定义td的单击事件)
2013/01/10 Javascript
node.js中的fs.linkSync方法使用说明
2014/12/15 Javascript
JS解析XML实例分析
2015/01/30 Javascript
通过XMLHttpRequest和jQuery实现ajax的几种方式
2015/08/28 Javascript
JavaScript 基础函数_深入剖析变量和作用域
2016/05/18 Javascript
微信小程序富文本渲染引擎的详解
2017/09/30 Javascript
微信小程序实现滑动切换自定义页码的方法分析
2018/12/29 Javascript
IE11下CKEditor在Bootstrap Modal中下拉问题的解决
2019/09/25 Javascript
浅谈vue 锚点指令v-anchor的使用
2019/11/13 Javascript
JavaScript基于用户照片姓名生成海报
2020/05/29 Javascript
python 数据加密代码
2008/12/24 Python
使用Python生成url短链接的方法
2015/05/04 Python
python爬虫实现教程转换成 PDF 电子书
2017/02/19 Python
利用python批量修改word文件名的方法示例
2017/10/17 Python
详解Python 函数如何重载?
2019/04/23 Python
Python类super()及私有属性原理解析
2020/06/15 Python
浅谈python 类方法/静态方法
2020/09/18 Python
HTML5 video标签(播放器)学习笔记(一):使用入门
2015/04/24 HTML / CSS
委托协议书范本
2014/04/22 职场文书
专业见习报告范文
2014/11/03 职场文书
2016年春节问候语
2015/11/11 职场文书
pytorch 权重weight 与 梯度grad 可视化操作
2021/06/05 Python
SQL Server 忘记密码以及重新添加新账号
2022/04/26 SQL Server
方法汇总:Python 安装第三方库常用
2022/04/26 Python
spring boot实现文件上传
2022/08/14 Java/Android
ubuntu20.04虚拟机无法上网的问题及解决
2022/12/24 Servers