if (options && options._isComponent) { //因为Vue动态合并策略非常慢,并且内部组件的选项都不需要特殊处理。 //调用initInternalComponent快捷方法,内部组件实例化。 initInternalComponent(vm, options); } else { vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ); }
function initInternalComponent (vm, options) { var opts = vm.$options = Object.create(vm.constructor.options); // 这样做是因为它比动态枚举更快。 var parentVnode = options._parentVnode; opts.parent = options.parent; opts._parentVnode = parentVnode; var vnodeComponentOptions = parentVnode.componentOptions; opts.propsData = vnodeComponentOptions.propsData; opts._parentListeners = vnodeComponentOptions.listeners; opts._renderChildren = vnodeComponentOptions.children; opts._componentTag = vnodeComponentOptions.tag; if (options.render) { opts.render = options.render; opts.staticRenderFns = options.staticRenderFns; } }
opts的结构如图所示:
局部注册和全局注册不同的是,只有该类型的组件才可以访问局部注册的子组件,而全局注册是扩展到 Vue.options 下。在所有组件创建的过程中,都会从全局的 Vue.options.components 扩展到当前组件的 vm.$options.components 下,这就是全局注册的组件能被任意使用的原因。
组件名定义
定义组件名的方式有两种:
使用短横线形式
Vue.component('button-counter', {})
引用这个自定义元素时,必须用 <button-counter></button-counter>
使用驼峰的形式
Vue.component('buttonCounter', { })
此时在引用这个自定义元素时,两种命名方法都可以使用。也就是说,<buttonCounter> 和 <button-counter> 都是可行的。
注意,直接在 DOM (即非字符串的模板) 中使用时只有短横线是有效的。如下:
<div> <button-counter></button-counter> </div>