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 相关文章推荐
Javacript实现颜色梯度变化和渐变的效果代码
May 31 Javascript
Javascript中String的常用方法实例分析
Jun 13 Javascript
JavaScript实现带箭头标识的多级下拉菜单效果
Aug 27 Javascript
Js得到radiobuttonlist选中值的两种方法(推荐)
Aug 25 Javascript
Node.js中的require.resolve方法使用简介
Apr 23 Javascript
详解vue-router和vue-cli以及组件之间的传值
Jul 04 Javascript
微信小程序使用scroll-view标签实现自动滑动到底部功能的实例代码
Nov 09 Javascript
javascript验证form表单数据的案例详解
Mar 25 Javascript
JS端基于download.js实现图片、视频时直接下载而不是打开预览
May 09 Javascript
小程序自动化测试的示例代码
Aug 11 Javascript
详解template标签用法(含vue中的用法总结)
Jan 12 Vue.js
js实现电灯开关效果
Jan 19 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边学边教》(04.编写简易的通讯录――视频教程1)
2006/12/13 PHP
php MYSQL 数据备份类
2009/06/19 PHP
使用XDebug调试及单元测试覆盖率分析
2011/01/27 PHP
php的urlencode()URL编码函数浅析
2011/08/09 PHP
PHP之浮点数计算比较以及取整数不准确的解决办法
2015/07/29 PHP
常用PHP封装分页工具类
2017/01/14 PHP
PHP实现向关联数组指定的Key之前插入元素的方法
2017/06/06 PHP
PHP获取当前系统时间的方法小结
2018/10/03 PHP
利用jQuery的$.event.fix函数统一浏览器event事件处理
2009/12/21 Javascript
jquery插件 autoComboBox 下拉框
2010/12/22 Javascript
jquery获取html元素的绝对位置和相对位置的方法
2014/06/20 Javascript
js判断手机和pc端选择不同执行事件的方法
2015/01/30 Javascript
使用JavaScript的AngularJS库编写hello world的方法
2015/06/23 Javascript
seajs加载jquery时提示$ is not a function该怎么解决
2015/10/23 Javascript
jQuery 移动端artEditor富文本编辑器
2016/01/11 Javascript
PhotoSwipe异步动态加载图片方法
2016/08/25 Javascript
关于 jQuery Easyui异步加载tree的问题解析
2016/12/06 Javascript
Vue中正确使用jQuery的方法
2017/10/30 jQuery
原生实现一个react-redux的代码示例
2018/06/08 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
2018/08/20 Javascript
React Native中Mobx的使用方法详解
2018/12/04 Javascript
layui 富文本编辑器和textarea值的相互传递方法
2019/09/18 Javascript
JQuery实现折叠式菜单的详细代码
2020/06/03 jQuery
如何使用JS console.log()技巧提高工作效率
2020/10/14 Javascript
python中的reduce内建函数使用方法指南
2014/08/31 Python
Python 和 JS 有哪些相同之处
2017/11/23 Python
Python 实现引用其他.py文件中的类和类的方法
2018/04/29 Python
Python编程图形库之Pillow使用方法讲解
2018/12/28 Python
python3正则提取字符串里的中文实例
2019/01/31 Python
Python如何处理大数据?3个技巧效率提升攻略(推荐)
2019/04/15 Python
Pandas 重塑(stack)和轴向旋转(pivot)的实现
2019/07/22 Python
Django models文件模型变更错误解决
2020/05/11 Python
Python爬虫实现百度翻译功能过程详解
2020/05/29 Python
Joules美国官网:出色的英国风格
2017/10/30 全球购物
2014年民警工作总结
2014/11/25 职场文书
年会邀请函的格式及范文五篇
2019/11/02 职场文书