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回调函数中会得到异步组件的定义。
posted @   楸枰~  阅读(276)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示