写点什么

【Vue2.x 源码学习】第三十五篇 - 组件部分 - Vue.component 实现

用户头像
Brave
关注
发布于: 刚刚
【Vue2.x 源码学习】第三十五篇 - 组件部分 - Vue.component 实现

一,前言

上篇,介绍了 Vue 组件与初始化流程,涉及以下几部分:


  • 组件使用介绍,包括:组件定义和优先级;

  • 组件的初始化流程介绍,包括:Vue.component、Vue.extend、全局组件构造函数保存、组件层级关系维护、组件合并、组件的渲染和更新;


本篇,主要介绍 Vue.component;


二,Vue.component 实现

1,Vue.component 如何加载


Vue.component 是全局 API;

在 Vue 初始化 init 时,会对全局 API 做集中处理:

// src/index.js
/** * 在vue 中所有的功能都通过原型扩展(原型模式)的方式来添加 * @param {*} options vue 实例化传入的配置对象 */function Vue(options) { this._init(options); // 调用Vue原型上的方法_init}
initMixin(Vue)renderMixin(Vue)lifeCycleMixin(Vue)initGlobalAPI(Vue) // 初始化 global Api
export default Vue;
复制代码


initGlobalAPI 方法,处理全局 API:

// src/global-api/index.js
export function initGlobalAPI(Vue) { // 全局属性:Vue.options // 功能:存放 mixin, component, filte, directive 属性 Vue.options = {}; Vue.mixin = function (options) { this.options = mergeOptions(this.options, options); return this; // 返回this,提供链式调用 } /** * Vue.component API * @param {*} id 组件名 * @param {*} definition 组件定义 */ Vue.component = function (id, definition) { }}
复制代码

2,Vue.component 如何定义

// 方法定义Vue.component = function (id, definition) {}  // 使用方式Vue.component('my-button',{  name:'my-button',  template:'<button>全局组件</button>'})
复制代码

2.1 组件名 name

每个组件都有一个自己的名字,即组件的唯一标识;


  • 默认组件名是:id,即 Vue.component 的第一个参数;

  • 若 definition 中有 name,使用 name 值作为组件名;

/**  * Vue.component  * @param {*} id          组件名  * @param {*} definition  组件定义  */Vue.component = function (id, definition) {  definition.name = definition.name || id;}
复制代码

2.2 组件定义 definition


Vue.component 的第二个参数 definition,即组件定义;

组件定义 definition 即可以是函数,也可以是对象:


  • Vue.extend({ /* ... */ }

  • { /* ... */ }

// 写法 1:注册组件,传入一个扩展过的构造器 Vue.component('my-component', Vue.extend({ /* ... */ })) 
// 写法 2:注册组件,传入一个选项对象 (自动调用 Vue.extend) Vue.component('my-component', { /* ... */ })
// 获取注册的组件 (始终返回构造器) var MyComponent = Vue.component('my-component')
复制代码


若入参 definition 为对象,则在 Vue.component 方法内部会使用 Vue.extend 进行一次处理:

// src/global-api/index.js
/** * 使用基础的 Vue 构造器,创造一个子类 * @param {*} definition */Vue.extend = function (definition) {
}
/** * Vue.component * @param {*} id 组件名 * @param {*} definition 组件定义:对象或函数 */Vue.component = function (id, definition) { // 获取组件名 name:优先使用definition.name,默认使用 id let name = definition.name || id; definition.name = name;
// 如果传入的 definition 是对象,需要用 Vue.extend 包裹 if(isObject(definition)){ definition = Vue.extend(definition) }}
复制代码


Vue.extend:使用基础的 Vue 构造器,创建一个子类;

下篇进行详细介绍:【Vue2.x 源码学习】第三十六篇 - Vue.extend 实现
复制代码

3,组件构造函数的全局保存

在 initGlobalAPI 方法中,Vue.options 用于存放全局属性;而在全局组件中,也会使用全局属性;所以,全局组件也要注册到 Vue.options 上;

所以,扩展Vue.options对象 Vue.options.components 用于存放全局组件:

// src/global-api/index.js
export function initGlobalAPI(Vue) { // 全局属性:Vue.options // 功能:存放 mixin, component, filte, directive 属性 Vue.options = {}; // 每个组件初始化时,将这些属性放入组件 // 用于存放全局组件 Vue.options.components = {}; /** * 使用基础的 Vue 构造器,创造一个子类 * @param {*} definition */ Vue.extend = function (definition) { } /** * Vue.component * @param {*} id 组件名(默认) * @param {*} definition 组件定义:可能是对象或函数 */ Vue.component = function (id, definition) {
// 获取组件名 name:优先使用definition.name,默认使用 id let name = definition.name || id; definition.name = name;
// 如果传入的 definition 是对象,需要用 Vue.extend 包裹 if(isObject(definition)){ definition = Vue.extend(definition) }
// 将 definition 对象保存到全局:Vue.options.components Vue.options.components[name] = definition;
}}
复制代码


Vue.options.components 就相当于在全局维护了一个组件名与组件构造函数的映射关系;

这样做的目的和作用:

  • 便于后续通过全局上的vm.constructor.options进行全局、局部组件的合并;

  • 便于后续根据组件虚拟节点的 tag 标签,能够直接查找到该组件的构造函数并进行组件的实例化;

4,Vue.component 总结

  • Vue.component 是 Vue Global API;

  • 通过调用 Vue.component 进行全局组件声明;

  • 在 Vue 初始化时,Vue.component 内部通过 Vue.extend 生成子类,即组件的构造函数;

  • 维护组件名与组件构造函数的映射关系到Vue.options.components 供后续组件合并与组件实例化使用;


三、结尾


备注:对组件初始化流程中的 Vue.component API 单独进行介绍,因此内容可能会上下不连贯,还会有一些遗漏,下周继续写组件初始化流程,过程中再持续进行补充和完善;


本篇,主要介绍了 Vue 初始化流程中的 Vue.component 实现:


  • Vue.component 全局 API 的初始化处理;

  • Vue.component 的定义和参数说明;

  • 组件构造函数全局存储的方式和作用;


下篇,Vue.extend 实现;

用户头像

Brave

关注

还未添加个人签名 2018.12.13 加入

还未添加个人简介

评论

发布
暂无评论
【Vue2.x 源码学习】第三十五篇 - 组件部分 - Vue.component 实现