首页 > 编程语言 >vue2源码-十六、异步组件

vue2源码-十六、异步组件

时间:2023-04-27 21:36:01浏览次数:36  
标签:异步 resolve comp factory 源码 vue2 组件 加载

异步组件

Vue 中异步组件的写法有很多,主要用作大的组件异步加载的markdown组件editor组件。就是先渲染一个注释标签,等组件加载完毕,最后再重新渲染 forceUpdate(图片懒加载)使用异步组件会配合 webpack

原理:异步组件默认不会调用 Vue.extend()方法 所有Ctor上没有cid属性,没有cid属性就是异步组件。会先渲染一个占位符组件,但是如果有loading会先渲染一个 loading,第一轮就结束了。如果用户调用 resolve,会将结果赋予给factory.resolve上面,强制重新渲染。重新渲染时候再次进到resolveAsyncComponent中,会直接拿到factory.resolve结果来渲染.

  • 使用

  • 使用工厂函数:

    Vue异步组件可以通过工厂函数来定义,这个工厂函数返回一个Promise对象,resolve后包含一个异步组件的定义。

    Vue.component('async-example', function (resolve, reject) {
      setTimeout(function () {
        resolve({
          template: '<div>I am async!</div>'
        })
      }, 1000)
    })
    
  • 使用import()语法

    Vue.component('async-webpack-example', () => import('./MyComponent.vue'))
    
  • 源码实现:

function ensureCtor(comp, base) {
  // 如果comp已经是一个构造函数,则直接返回
  if (comp.__esModule || (typeof comp === 'object' && comp.default)) {
    // 支持 ES2015 export default 和 module.exports 导出模块
    comp = comp.default;
  }
  return isObject(comp)
    ? base.extend(comp)
    : comp;
}

function createAsyncPlaceholder(factory, data, context, children, tag) {
  const node = createEmptyVNode();
  node.asyncFactory = factory;
  node.asyncMeta = { data, context, children, tag };
  return node;
}

export function resolveAsyncComponent(
  factory: Function,
  baseCtor: Class<Component>
): Class<Component> | void {
  // 如果 factory 的类型是 Promise,则返回通过 Promise.resolve 包装过后的 factory,
  if (isTrue(factory.error) && isDef(factory.errorComp)) {
    // 如果 asyncFactory 是一个错误的异步组件工厂函数(例如因为加载组件时发生错误),则返回错误组件实例
    return factory.errorComp;
  }

  // 已解决,factory 要么是一个渲染函数,要么是一个组件对象
  if (isDef(factory.resolved)) {
    return factory.resolved;
  }

  // 这里判断异步组件是否正在加载中,如果正在加载中,则会将该异步组件在等待列表中添加一份到一个数组中, 然后直接返回继续等待
  if (isDef(factory.loading) && !isDef(factory.loadingComp)) {
    factory.loadingComp = createAsyncPlaceholder(
      // 异步组件的工厂函数
      factory.loading,
      baseCtor,
      undefined,
      undefined,
      undefined
    );
    loadAndDefineAsyncComponent(factory, baseCtor);
  }

  return factory.loadingComp;
}

function loadAndDefineAsyncComponent(factory, baseCtor) {
  // 如果工厂函数是一个异步导入函数(即返回Promise的函数)
  if (isUndef(factory.resolved)) {
    // 异步加载并解析组件,同时定义一个resolve回调函数
    factory.resolved = true; // 标记为已resolved

    factory(
      // 异步组件定义的成功回调
      comp => {
        // 如果解析出来的comp是一个对象,则将其转化为Vue构造器
        if (isObject(comp)) {
          comp = ensureCtor(comp, baseCtor);
          if (comp === baseCtor) {
            return;
          }
        }
        // 给异步组件定义附加上一些常用的属性
        factory.resolved = comp;
      },
      // 定义组件加载失败后的处理函数,将error和errorComp打上标记
      error => {
        factory.error = true;
        factory.errorComp = ensureCtor(error, baseCtor);
      }
    );
  }
}
  • resolveAsyncComponent方法会根据异步组件的状态返回不同的结果,如果该组件已经被解析出来,就直接返回它的构造函数;如果还在加载中,则返回一个异步占位符;如果加载出错,则返回错误组件。
  • loadAndDefineAsyncComponent方法则实现了异步组件的加载和定义,它使用给定的工厂函数来加载和解析组件,并在加载成功后将该组件转换为Vue构造器。其中,工厂函数是一个异步导入函数,会返回一个Promise对象,在resolve回调函数中会得到异步组件的定义。

标签:异步,resolve,comp,factory,源码,vue2,组件,加载
From: https://www.cnblogs.com/dgqp/p/17360257.html

相关文章

  • ubuntu2004 下源码安装boost
    ubuntu2004下源码安装boosthttps://www.aiuai.cn/aifarm1186.htmlhttps://www.boost.org/users/history/version_1_78_0.htmlhttps://cloud.tencent.com/developer/article/1804511https://stackoverflow.com/questions/12578499/how-to-install-boost-on-ubuntuboost版本在......
  • Vue2实现部分页面使用rem布局
    1.计算rem值的比例,这里是1920的设计图;setRem(){/***@file:index.vue*@method:setRemPc*@param:*@return:*@description:计算rem大小*@date:*/varwhdef=100/1920;//表示1920的设计图,使用100PX的默认值varbodyWidth=document.body.cli......
  • vue2实现饼图Pie组件封装
    实现如下效果: 如果不会请移步到官网的栗子,请点击查看直接给大家上代码:整体代码片段1<template>2<divref="echarts"style="width:100%;height:300px;"></div>3</template>4<script>5/*eslint-disable*/6import{setPieOpt......
  • vue2 input防抖功能
    1.在el-input绑定@input事件 2.在data中定义timer为null 3.在methods中定义@input绑定的方法 4.在setTimeout中调用对应处理的方法<el-inputstyle="width:140px;color:#FF8900"size="small"v-model="singleDiscountForm.discount"@input="inputDis......
  • 直播平台搭建源码,使用EasyExcel实现导入导出功能
    直播平台搭建源码,使用EasyExcel实现导入导出功能使用,添加依赖 <dependencies> <!--https://mvnrepository.com/artifact/com.alibaba/easyexcel--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>......
  • 直播软件源码,好看的点赞按钮
    直播软件源码,好看的点赞按钮 <divid="mountNode"></div>classButtonextendsReact.Component{  state={  starred:false, };   handleClick(){  this.setState({   ...this.state,   starred:!this.state.starred,  }); };   ......
  • 安装多个NodeJS windows上安装多个Nodejs版本 解决vue2/vue3同时运行
    第一步下载nvm-windowsnvm-windows下载地址:Github最新下载地址进入之后直接下载第二步安装NVM注意路径一定不要包含空格中文否则会报错注意安装路径一定不要包含空格中文否则会报错 点击安装之后如果之前安装了nodejs的话会提示希望nvm管理已安装node版本吗点击是......
  • vue2与vue3的区别
    一.vue2和vue3双向数据绑定原理发生了改变vue2的双向数据绑定是利用ES5的一个APIObject.definePropert()对数据进行劫持结合发布订阅模式的方式来实现的。vue3中使用了es6的ProxyAPI对数据代理。相比于vue2.x,使用proxy的优势如下defineProperty只能监听某个属性,不......
  • 直播系统源码开发之对接腾讯云即时通讯im
    概述什么是直播系统?什么是即时通讯?腾讯云即时通讯IM简介直播系统源码开发直播系统搭建流程直播系统开源代码介绍对接腾讯云即时通讯IM什么是腾讯云即时通讯IM?腾讯云IMSDK集成腾讯云IMSDK对接流程腾讯云IMSDK集成IMSDK介绍IMSDK的功能介绍IMSDK的使用限制腾讯云IMSDK对接流程......
  • License授权文件生成器源码
    功能介绍1.对销售后的软件或网站执行版权控制,防止被非法另行出售;2.对网站域名进行有效的管理监控,防止非法域名或未授权域名;3.防止黑客使用极端手段获取网站或程序原文件后非法部署;系统功能:1.完整版Lisence生成工具。2.对网站使用域名执行控制。3.对网站域名使用时间执行授权控制......