全局组件通过Vue.component注册,而Vue.component的定义是在initGlobalAPI(Vue);--->initAssetRegisters(Vue)。ASSET_TYPES数组中有'component'字符串。Vue.component(id, definition)方法的逻辑是:用Vue.extend方法,生成一个Vue的子类VueComponent,(这是个构造函数,是用来生成子组件实例的),接着把VueComponent赋值给Vue.options.components[id]属性。这里就显得很熟悉,我们知道,在生成虚拟节点中多个方法里面,最最重要的是的vm._c方法也就是createElement方法,里面的逻辑会先递归判断当前tag是否reserved,如果不是,要去vm.$options.components中找这个tag,(在vm_init方法中,在调用$mount方法生成真实节点之前,会调用mergeOptions方法,将Vue上的属性(这里面就包含components属性)和vm的new Vue(options)方法中参数options合并,在赋值给vm的$options属性,所以vm是能获取到Vue上的全局组件信息的),注意此时vm.$options.components中不仅包含全局组件,还包括局部组件。局部组件的元数据信息可以由.vue文件编译而来,也可以写在父组件的components属性指向的对象的属性中,那么这里可以写一个对象,比如{name: '', data: {}, template: '', mounted: ()=>{}}这样的格式,也可以是上面全局组件中的直接指向一个子组件的构造函数。如果是对象格式,在createElement中其实还是要在vnode= createComponent()方法中调用Vue.extend方法,生成一个Ctor赋值给vnode的ctor属性,在mount--update--patch方法中,生成vm实例和真实节点。注意,在extend方法中,会把Vue的options和全局/局部 组件的原信息 进行合并,放到VueComponent的options属性中,然后在子组件vm的_init方法中,进入initInternalComponent方法,作为 vm.$options的原型对象,接着再合并几个附加属性,就是所有的子组件vm的元数据。