Vue.js源码分析 - 组件化

460 阅读3分钟

「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战

Vue.js源码分析 - 组件化

接下来我们要进行回顾Vue的组件化,组件化是Vue中的一个很重要的概念,Vue的核心组成就是数据绑定组件化

组件化.webp

组件化回顾

  • 一个 Vue 组件就是一个拥有预定义选项的一个 Vue 实例
  • 一个组件可以组成可以组成页面上一个功能完毕的区域,组件可以包含
    • 脚本
    • 样式
    • 模板 就和下图一样,我们可以把页面分割成很多的模块,到时候我们可以按需拼接在一起,就和积木块一样,每一个组件中可能有嵌套了其他颗粒度更小的组件,让我们可以更方便的可以进行复用 image.png

这就引发了一个问题:

  • 组件的颗粒度是越小越好吗?
  • 我们先带着这个问题进入下面的复习,之后在进行解答 da0f8e9f2cdabfb1ad82f4d154b56192.jpg

组件注册

我们先来回顾下 组件的注册方式

  • 全局注册:在页面中任意的范围都可以进行使用
  • 局部注册:仅仅在当前注册范围中可以使用 接下来我们通过一段代码来回忆一下组件的注册方式
Vue.component('comp', {
      template: '<h1>hello</h1>'
})

下来我们来看一下Vue.component的实现

component

Vue.component是一个静态方法

  • 路径:src\core\global-api\assets.js
  • 创建组件的构造函数,挂载到 Vue 实例的 vm.options.component.componentName = Ctor
// src\core\global-api\index.js
// 注册 Vue.directive()、 Vue.component()、Vue.filter()
initAssetRegisters(Vue)

// src\core\global-api\assets.js
if (type === 'component' && isPlainObject(definition)) {
    definition.name = definition.name || id
    definition = this.options._base.extend(definition)
}

……

// 全局注册,存储资源并赋值
// this.options['components']['comp'] = Ctor
this.options[type + 's'][id] = definition

// src\core\global-api\index.js
// this is used to identify the "base" constructor to extend all plain-object
// components with in Weex's multi-instance scenarios.

Vue.options._base = Vue

// src\core\global-api\extend.js

Vue.extend()

extend

Vue.component中,如果第二个参数传入的是一个组件选项对象的话,它内部会调用Vue.extend方法把该组件的选项对象转换成对应的选项子类,也就是对应组件的构造函数,所以我们会说:组件也是一个Vue实例

  • 路径 src\core\global-api\extend.js
const Sub = function VueComponent (options) {
    this._init(options)
}

Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub
Sub.cid = cid++
Sub.options = mergeOptions(
    Super.options,
    extendOptions
)
Sub['super'] = Super

// For props and computed properties, we define the proxy getters on
// the Vue instances at extension time, on the extended prototype. This
// avoids Object.defineProperty calls for each instance created.
if (Sub.options.props) {
    initProps(Sub)
}

if (Sub.options.computed) {
    initComputed(Sub)
}

// allow further extension/mixin/plugin usage
Sub.extend = Super.extend
Sub.mixin = Super.mixin
Sub.use = Super.use

// create asset registers, so extended classes
// can have their private assets too.
ASSET_TYPES.forEach(function (type) {
    Sub[type] = Super[type]
})

// enable recursive self-lookup
if (name) {
    Sub.options.components[name] = Sub
}

组件的颗粒度是越小越好吗?

  1. 前面说过,组件是支持嵌套的,所以整个组件树的挂载过程,就是一个递归挂载组件的过程。
  2. 在组件的挂载过程中,除了前面说的创建和渲染 vnode 之外,内部还创建了一个组件实例,用来维护组件的状态和数据,此外,还有组件初始化阶段的一些响应式数据处理,这些都是有一定耗时和内存占用的
  3. 因此,如果我们拆分组件的粒度过细,会导致嵌套组件过深,显而易见的是整个应用的初始化时长会变长,占用的内存空间也会变大
  4. 不仅如此 组件的事件调用、数据流传也会随着嵌套的增加,而变得难以维护,也就是你在开发之前,就需要了解每一个组件的数据流转、参数需求等;当传参不明确的情况下(如下),工程量就变得非常大了
    props: {
        参数1: {
          type: Object,
          default: () => {}
        },
        参数2: {
          type: any,
          default: undefined
        }
     },
    

所以从性能到后期的维护,组件的颗粒度并不是越小越好!一切还是要以性能业务层面分析为主,而不是个人喜好

好了到这里本章就完结了,求点赞!评论!收藏! src=http___dingyue.ws.126.net_1kNX5UOlvvZhqzVi4eMVTefclpP9NYP6nSIQPkU9McOAq1553651252093compressflag.jpg&refer=http___dingyue.ws.126.jpg