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 相关文章推荐
验证用户是否修改过页面的数据的实现方法
Sep 26 Javascript
jquery 图片预加载 自动等比例缩放插件
Dec 25 Javascript
Prototype ObjectRange对象学习
Jul 19 Javascript
javascript 数组排序函数sort和reverse使用介绍
Nov 21 Javascript
javascript 中的 delete及delete运算符
Nov 15 Javascript
深入剖析JavaScript:Object类型
May 10 Javascript
解决vue页面DOM操作不生效的问题
Mar 17 Javascript
JavaScript封装的常用工具类库bee.js用法详解【经典类库】
Sep 03 Javascript
JS基于Location实现访问Url、重定向及刷新页面的方法分析
Dec 03 Javascript
jQuery/JS监听input输入框值变化实例
Oct 17 jQuery
Vue中import from的来源及省略后缀与加载文件夹问题
Feb 09 Javascript
vue封装自定义指令之动态显示title操作(溢出显示,不溢出不显示)
Nov 12 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网上调查系统
2006/10/09 PHP
PHP Google的translate API代码
2008/12/10 PHP
PHP MySql增删改查的简单实例
2016/06/21 PHP
php的api数据接口书写实例(推荐)
2016/09/22 PHP
PHP开发中解决并发问题的几种实现方法分析
2017/11/13 PHP
TP5(thinkPHP5)框架使用ajax实现与后台数据交互的方法小结
2020/02/10 PHP
jquery 入门教程 [翻译] 推荐
2009/08/17 Javascript
在ASP.NET中使用JavaScript脚本的方法
2013/11/12 Javascript
jQuery动态改变图片显示大小(修改版)的实现思路及代码
2013/12/24 Javascript
JavaScript中的Math.E属性使用详解
2015/06/12 Javascript
JavaScript实现跨浏览器的添加及删除事件绑定函数实例
2015/08/04 Javascript
require.js的用法详解
2015/10/20 Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
2016/09/04 Javascript
JavaScript  event对象整理及详细介绍
2016/10/10 Javascript
jQuery webuploader分片上传大文件
2016/11/07 Javascript
浅谈Nodejs中的作用域问题
2016/12/26 NodeJs
浅谈Angular2 模块懒加载的方法
2017/10/04 Javascript
vue-dplayer 视频播放器实例代码
2019/11/08 Javascript
用Python实现斐波那契(Fibonacci)函数
2016/03/25 Python
Python的Flask框架应用程序实现使用QQ账号登录的方法
2016/06/07 Python
分析Python中解析构建数据知识
2018/01/20 Python
python的pstuil模块使用方法总结
2019/07/26 Python
PyQt5通信机制 信号与槽详解
2019/08/07 Python
下载官网python并安装的步骤详解
2019/10/12 Python
Python descriptor(描述符)的实现
2020/11/15 Python
Coach澳大利亚官方网站:美国著名时尚奢侈品牌
2017/05/24 全球购物
美国修容界大佬创建的个人美妆品牌:Kevyn Aucoin Beauty
2018/12/12 全球购物
优秀员工年终发言演讲稿
2014/01/01 职场文书
行政文秘岗位职责范本
2014/02/10 职场文书
拔河比赛口号
2014/06/10 职场文书
幼儿园六一儿童节活动方案
2014/08/26 职场文书
服务行业演讲稿
2014/09/02 职场文书
2016应届毕业生实习评语
2015/12/01 职场文书
阳光体育运动标语口号
2015/12/26 职场文书
MySQL的安装与配置详细教程
2021/06/26 MySQL
深入理解go slice结构
2021/09/15 Golang