- 5.1 组件两种注册方式
- 5.1.1 全局注册
- 5.1.2 局部注册
- 5.1.3 注册过程
5.1 组件两种注册方式
熟悉Vue
开发流程的都知道,Vue
组件在使用之前需要进行注册,而注册的方式有两种,全局注册和局部注册。在进入源码分析之前,我们先回忆一下两者的用法,以便后续掌握两者的差异。
5.1.1 全局注册
Vue.component('my-test', {
template: '<div>{{test}}</div>',
data () {
return {
test: 1212
}
}
})
var vm = new Vue({
el: '#app',
template: '<div id="app"><my-test><my-test/></div>'
})
其中组件的全局注册需要在全局实例化Vue前调用,注册之后可以用在任何新创建的Vue
实例中调用。
5.1.2 局部注册
var myTest = {
template: '<div>{{test}}</div>',
data () {
return {
test: 1212
}
}
}
var vm = new Vue({
el: '#app',
component: {
myTest
}
})
当只需要在某个局部用到某个组件时,可以使用局部注册的方式进行组件注册,此时局部注册的组件只能在注册该组件内部使用。
5.1.3 注册过程
在简单回顾组件的两种注册方式后,我们来看注册过程到底发生了什么,我们以全局组件注册为例。它通过Vue.component(name, {...})
进行组件注册,Vue.component
是在Vue
源码引入阶段定义的静态方法。
// 初始化全局api
initAssetRegisters(Vue);
var ASSET_TYPES = [
'component',
'directive',
'filter'
];
function initAssetRegisters(Vue){
// 定义ASSET_TYPES中每个属性的方法,其中包括component
ASSET_TYPES.forEach(function (type) {
// type: component,directive,filter
Vue[type] = function (id,definition) {
if (!definition) {
// 直接返回注册组件的构造函数
return this.options[type + 's'][id]
}
...
if (type === 'component') {
// 验证component组件名字是否合法
validateComponentName(id);
}
if (type === 'component' && isPlainObject(definition)) {
// 组件名称设置
definition.name = definition.name || id;
// Vue.extend() 创建子组件,返回子类构造器
definition = this.options._base.extend(definition);
}
// 为Vue.options 上的component属性添加将子类构造器
this.options[type + 's'][id] = definition;
return definition
}
});
}
Vue.components
有两个参数,一个是需要注册组件的组件名,另一个是组件选项,如果第二个参数没有传递,则会直接返回注册过的组件选项。否则意味着需要对该组件进行注册,注册过程先会对组件名的合法性进行检测,要求组件名不允许出现非法的标签,包括Vue
内置的组件名,如slot, component
等。
function validateComponentName(name) {
if (!new RegExp(("^[a-zA-Z][\\-\\.0-9_" + (unicodeRegExp.source) + "]*$")).test(name)) {
// 正则判断检测是否为非法的标签
warn(
'Invalid component name: "' + name + '". Component names ' +
'should conform to valid custom element name in html5 specification.'
);
}
// 不能使用Vue自身自定义的组件名,如slot, component,不能使用html的保留标签,如 h1, svg等
if (isBuiltInTag(name) || config.isReservedTag(name)) {
warn(
'Do not use built-in or reserved HTML elements as component ' +
'id: ' + name
);
}
}
在经过组件名的合法性检测后,会调用extend
方法为组件创建一个子类构造器,此时的this.options._base
代表的就是Vue
构造器。extend
方法的定义在介绍选项合并章节有重点介绍过,它会基于父类去创建一个子类,此时的父类是Vue
,并且创建过程子类会继承父类的方法,并会和父类的选项进行合并,最终返回一个子类构造器。
代码处还有一个逻辑,Vue.component()
默认会把第一个参数作为组件名称,但是如果组件选项有name
属性时,name
属性值会将组件名覆盖。
总结起来,全局注册组件就是Vue
实例化前创建一个基于Vue
的子类构造器,并将组件的信息加载到实例options.components
对象中。
接下来自然而然会想到一个问题,局部注册和全局注册在实现上的区别体现在哪里?我们不急着分析局部组件的注册流程,先以全局注册的组件为基础,看看作为组件,它的挂载流程有什么不同。