vue源码分析-组件

本文详细分析了Vue.js中的异步组件和函数式组件,探讨了它们的使用场景、工厂函数、流程以及Webpack的配合使用。异步组件用于优化首屏加载时间,通过工厂函数实现按需加载,减少脚本体积。函数式组件无状态、无实例,降低了渲染开销,适用于多组件选择和数据预处理。
摘要由CSDN通过智能技术生成

我们知道,组件是Vue体系的核心,熟练使用组件是掌握Vue进行开发的基础。上一节中,我们深入了解了Vue组件注册到使用渲染的完整流程。这一节我们会在上一节的基础上介绍组件的两个高级用法:异步组件和函数式组件。

6.1 异步组件

6.1.1 使用场景

Vue作为单页面应用遇到最棘手的问题是首屏加载时间的问题,单页面应用会把页面脚本打包成一个文件,这个文件包含着所有业务和非业务的代码,而脚本文件过大也是造成首页渲染速度缓慢的原因。因此作为首屏性能优化的课题,最常用的处理方法是对文件的拆分和代码的分离。按需加载的概念也是在这个前提下引入的。我们往往会把一些非首屏的组件设计成异步组件,部分不影响初次视觉体验的组件也可以设计为异步组件。这个思想就是按需加载。通俗点理解,按需加载的思想让应用在需要使用某个组件时才去请求加载组件代码。我们借助webpack打包后的结果会更加直观。

在这里插入图片描述

在这里插入图片描述

webpack遇到异步组件,会将其从主脚本中分离,减少脚本体积,加快首屏加载时间。当遇到场景需要使用该组件时,才会去加载组件脚本。

6.1.2 工厂函数

Vue中允许用户通过工厂函数的形式定义组件,这个工厂函数会异步解析组件定义,组件需要渲染的时候才会触发该工厂函数,加载结果会进行缓存,以供下一次调用组件时使用。
具体使用:

// 全局注册:
Vue.component('asyncComponent', function(resolve, reject) {
   
  require(['./test.vue'], resolve)
})
// 局部注册:
var vm = new Vue({
   
  el: '#app',
  template: '<div id="app"><asyncComponent></asyncComponent></div>',
  components: {
   
    asyncComponent: (resolve, reject) => require(['./test.vue'], resolve),
    // 另外写法
    asyncComponent: () => import('./test.vue'),
  }
})
6.1.3 流程分析

有了上一节组件注册的基础,我们来分析异步组件的实现逻辑。简单回忆一下上一节的流程,实例的挂载流程分为根据渲染函数创建Vnode和根据Vnode产生真实节点的过程。期间创建Vnode过程,如果遇到子的占位符节点会调用creatComponent,这里会为子组件做选项合并和钩子挂载的操作,并创建一个以vue-component-为标记的子Vnode,而异步组件的处理逻辑也是在这个阶段处理。参考Vue3源码视频讲解:进入学习

// 创建子组件过程
  function createComponent (
    Ctor, // 子类构造器
    data,
    context, // vm实例
    children, // 子节点
    tag // 子组件占位符
  ) {
   
    ···
    // 针对局部注册组件创建子类构造器
    if (isObject(Ctor)) {
   
      Ctor = baseCtor.extend(Ctor);
    }
    // 异步组件分支
    var asyncFactory;
    if (isUndef(Ctor.cid)) {
   
      // 异步工厂函数
      asyncFactory = Ctor;
      // 创建异步组件函数
      Ctor = resolveAsyncComponent(asyncFactory, baseCtor);
      if (Ctor === undefined) {
   
        return createAsyncPlaceholder(
          asyncFactory,
          data,
          context,
          children,
          tag
        )
      }
    }
    ···
    // 创建子组件vnode
    var vnode = new VNode(
      ("vue-component-" + (Ctor.cid) + (name ? ("-" + name) : '')),
      data, undefined, undefined, undefined, context,
      {
    Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children },
      asyncFactory
    );

    return vnode
  }

**工厂函数的用法使得Vue.component(name, options)的第二个参数不是一个对象,因此不论是全局注册还是局部注册,都不会执行Vue.extend生成一个子组件的构造器,**所以Ctor.cid不会存在,代码会进入异步组件的分支。

异步组件分支的核心是resolveAsyncComponent,它的处理逻辑分支众多,我们先关心工厂函数处理部分。

function resolveAsyncComponent (
    factory,    baseCtor  ) {
   
    if (!isDef(factory.owners)) {
   

      // 异步请求成功处理
      var resolve 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值