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 相关文章推荐
基于jQuery的遍历同id元素 并响应事件的代码
Jun 14 Javascript
jquery validate poshytip 自定义样式
Nov 26 Javascript
如何使用jquery动态加载js,css文件实现代码
Apr 03 Javascript
表单提交前触发函数返回true表单才会提交
Mar 11 Javascript
window.location不跳转的问题解决方法
Apr 17 Javascript
把文本中的URL地址转换为可点击链接的JavaScript、PHP自定义函数
Jul 29 Javascript
JS实现点击按钮后框架内载入不同网页的方法
May 05 Javascript
JavaScript表单验证实现代码
May 22 Javascript
详解React 服务端渲染方案完美的解决方案
Dec 14 Javascript
一文读懂ES7中的javascript修饰器
May 06 Javascript
js实现跟随鼠标移动的小球
Aug 26 Javascript
微信小程序实现菜单左右联动
May 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
How do I change MySQL timezone?
2008/03/26 PHP
PHP遍历并打印指定目录下所有文件实例
2014/02/10 PHP
老生常谈PHP位运算的用途
2017/03/12 PHP
PHP后期静态绑定之self::限制实例分析
2018/12/21 PHP
详解PHP中的8个魔术常量
2020/07/06 PHP
利用404错误页面实现UrlRewrite的实现代码
2008/08/20 Javascript
JavaScript Event学习第七章 事件属性
2010/02/07 Javascript
js(jQuery)获取时间的方法及常用时间类搜集
2013/10/23 Javascript
更快的异步执行(setTimeout多浏览器)
2014/08/12 Javascript
一款简单的jQuery图片标注效果附源码下载
2016/03/22 Javascript
jQuery过滤特殊字符及JS字符串转为数字
2016/05/26 Javascript
JS判断form内所有表单是否为空的简单实例
2016/09/09 Javascript
node.js实现登录注册页面
2017/04/08 Javascript
微信小程序 navbar实例详解
2017/05/11 Javascript
JS基于正则表达式实现的密码强度验证功能示例
2017/09/21 Javascript
Angular Renderer (渲染器)的具体使用
2018/05/03 Javascript
iconfont的三种使用方式详解
2018/08/05 Javascript
bootstrap动态调用select下拉框的实例代码
2018/08/09 Javascript
Vue+Element UI+Lumen实现通用表格分页功能
2019/02/02 Javascript
[02:44]DOTA2英雄基础教程 钢背兽
2013/12/19 DOTA
学习python (2)
2006/10/31 Python
py中的目录与文件判别代码
2008/07/16 Python
Python使用MD5加密字符串示例
2014/08/22 Python
Python使用PyCrypto实现AES加密功能示例
2017/05/22 Python
pandas数据选取:df[] df.loc[] df.iloc[] df.ix[] df.at[] df.iat[]
2020/04/24 Python
python boto和boto3操作bucket的示例
2020/10/30 Python
使用css3背景渐变中的透明度来设置不同颜色的背景渐变
2014/03/31 HTML / CSS
CSS3对背景图片的裁剪及尺寸和位置的设定方法
2016/03/07 HTML / CSS
意大利奢侈品购物网站:Giglio
2018/01/05 全球购物
学校教师安全责任书
2014/07/23 职场文书
乱丢垃圾袋检讨书
2014/10/08 职场文书
2014年残疾人工作总结
2014/12/06 职场文书
会议欢迎词范文
2015/01/27 职场文书
邀请函模板
2015/02/02 职场文书
Java比较两个对象中全部属性值是否相等的方法
2021/08/07 Java/Android
nginx 配置指令之location使用详解
2022/05/25 Servers