「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战」
Vue.js源码分析 - 组件化
接下来我们要进行回顾Vue
的组件化,组件化是Vue
中的一个很重要的概念,Vue
的核心组成就是数据绑定和组件化
组件化回顾
- 一个 Vue 组件就是一个拥有预定义选项的一个 Vue 实例
- 一个组件可以组成可以组成页面上一个功能完毕的区域,组件可以包含
- 脚本
- 样式
- 模板 就和下图一样,我们可以把页面分割成很多的模块,到时候我们可以按需拼接在一起,就和积木块一样,每一个组件中可能有嵌套了其他颗粒度更小的组件,让我们可以更方便的可以进行复用
这就引发了一个问题:
- 组件的颗粒度是越小越好吗?
- 我们先带着这个问题进入下面的复习,之后在进行解答
组件注册
我们先来回顾下 组件的注册方式
- 全局注册:在页面中任意的范围都可以进行使用
- 局部注册:仅仅在当前注册范围中可以使用 接下来我们通过一段代码来回忆一下组件的注册方式
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
}
组件的颗粒度是越小越好吗?
- 前面说过,组件是支持嵌套的,所以整个组件树的挂载过程,就是一个递归挂载组件的过程。
- 在组件的挂载过程中,除了前面说的创建和渲染
vnode
之外,内部还创建了一个组件实例,用来维护组件的状态和数据,此外,还有组件初始化阶段的一些响应式数据处理,这些都是有一定耗时和内存占用的。 - 因此,如果我们拆分组件的粒度过细,会导致嵌套组件过深,显而易见的是整个应用的初始化时长会变长,占用的内存空间也会变大。
- 不仅如此 组件的事件调用、数据流传也会随着嵌套的增加,而变得难以维护,也就是你在开发之前,就需要了解每一个组件的数据流转、参数需求等;当传参不明确的情况下(如下),工程量就变得非常大了!
props: { 参数1: { type: Object, default: () => {} }, 参数2: { type: any, default: undefined } },
所以从性能到后期的维护,组件的颗粒度并不是越小越好!一切还是要以性能、业务层面分析为主,而不是个人喜好
好了到这里本章就完结了,求点赞!评论!收藏!