Vue.component 用来注册或获取一个全局的组件,为什么说它是全局呢?因为通过该方法注册的组件都会添加到Vue.options.components
中. ( Vue.directive 和 Vue.filter 也是同理)
下文中用 components
代替. 实际上Vue.component() 也只是 Vue.extend
的一层封装
Vue['component'] = function(id,options) {
if(!options) {
return this.options['components'][id]
}
// type 由上文传入的,
if(type == "component" && options === "[object Object]") {
options = this.options._base.extend(options)
}
this.options['components'][id] = options
return options
}
参照官方文档的使用方法来逐一分析:
if(!options) {
return this.options['components'][id]
}
Vue.component("comp",Vue.component(...))
[object Object]类型
时,则调用 Vue.extend
创建一个组件添加到 components
中.为什么要这样判断呢?因为通过Vue.extend创建的组件的类型是[object Function]
(Vuecomponent构造函数)使用基础 Vue 构造器,创建一个“子类”
Vuecomponent
函数.它最终会返回作为一个组件的构造函数,也就上面提到的一个“子类”。内部的 this._init
也就是与Vue初始化时一致的方法
var Super = this // this == Vue
var Sub = function Vuecomponent(extendOptions) {
this._init(extendOptions)
}
然后设置子类的prototype继承了Vue原型
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = sub
这一步至关重要,将用户传入的配置与 Super.options合并, Super.options上有一些基础的全局组件和指令, 这里的 Super.options 也就是 Vue.options
Sub.options = mergeOptions(
Super.options, // Vue.construct.options
extendOptions // 用户传入的配置
)
初始的 Super.options
{
components: {
KeepAlive,
Transition,
TransitionGroup
},
directives: {
model,
show
},
filters:{},
_base: Vue
}
接着在Sub上添加一个 “super” 属性,通过它就可以知道该构造函数是不是继承而来的.
Sub["super"] = Super
接下来把 props 和 computed 代理到 Sub.prototype
上, 没搞懂这么做啥意思,等后面有头绪了再来补充。
if(Sub.options.props) {
initProps$1(Sub)
}
if(Sub.options.computed) {
initComputed$1(Sub)
}
添加一份对Super.options的引用,在后面初始化的时候, 如果验证Super.options与Vue.options不一致,则重新更新 superOptions
Sub.superOptions = Super.options
Sub.extendOptions = extendOptions
Sub.sealedOptions = extend({},Sub.options)
最后返回了 Vuecomponent构造函数
,至此Vue.extend的工作就结束了
return Sub
完整代码:
Vue.extend = function(extendOptions) {
extendOptions = extendOptions || {}
var Super = this
var SuperId = Super.cid
var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
if(cachedCtors[SuperOd]) {
return cachedCtors[SuperId]
}
var name = extendOptions.name || Super.options.name
if(name) {
// 校验组件名是否合规
validateComponentName(name)
}
var 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
if(Sub.options.prop) {
initProps$1(Sub)
}
if(Sub.options.computed) {
initComputed$1(Sub)
}
Sub.extend = Super.extend
Sub.mixin = Super.mixin
Sub.use = Super.use
ASSET_TYPE.foreach(function(type){
Sub[type] = Super[type]
})
if(name) {
Sub.options.components[name] = Sub
}
Sub.superOptions = Super.options
Sub.extendOptions = extendOptions
Sub.sealeOptions = extend({},Sub.options)
cachedCtors[SuperId] = Sub
return Sub
}
mixin代码很简单,它是mergeOptions
的封装
// @params mixin 用户传入的配置
Vue.mixin = function(mixin) {
this.options = mergeOptions(this.options,mixin)
return this
}