最近在React项目中使用了公司官方的图标库。以往Vue项目中使用的图标库都是全局注册的,这样就可以直接在组件中使用图标组件,无需手动导入再注册组件。但是目前的React没有办法像Vue那样实现全局注册,只能手动导入。所以很好奇,Vue是怎么实现全局注册的。在之前的项目中,看到过这样的用法:Vue.prototype.$axios=axios;在上面的代码中,axios挂载在Vue原型对象上,这样this.$axios访问axois,即实现全局注册。在看源码之前,可以大胆猜测组件全局注册应该是将组件挂载在Vue构造函数上,这样每一个这样创建的Vue实例都会在$options中包含这个组件,这样就可以直接使用了。Vue.component的使用方法在看源码之前,先看看官方文档中的描述,比较容易理解。//{String}id//{函数|Object}[definition]Vue.component(id,[definition])这个api的作用是注册或者获取全局组件。注册还会自动使用给定的id设置组件的名称。//注册组件,传入一个扩展构造函数Vue.component('my-component',Vue.extend({/*...*/}))//注册组件,传入一个选项对象(autoCallVue.extend)Vue.component('my-component',{/*...*/})//获取注册的组件(总是返回构造函数)varMyComponent=Vue.component('my-component')源码分析出处Vue.component的代码在这个目录下:node_modules\vue\src\core\global-api\assets.js但是看源码之前,先看一下global-api\index.js。这部分主要是初始化Vue构造函数,并在其上挂载各种全局API。然后在第54行,有这么一段代码:Vue.options=Object.create(null)ASSET_TYPES.forEach(type=>{Vue.options[type+'s']=Object.create(null)})这里的作用是在Vue上初始化一个options对象,然后这个对象的key从这里来:exportconstASSET_TYPES=['component','directive','filter']这段代码执行后,应该得到这个:Vue.options={components:{},directives:{},filters:{}}然后在global-api\index.js:68中有这么一段代码:initAssetRegisters(Vue)initAssetRegisters函数定义在global-api\assets.js,我们来看看:import{ASSET_TYPES}from'shared/constants'import{isPlainObject,validateComponentName}from'../util/index'exportfunctioninitAssetRegisters(Vue:GlobalAPI){/***创建资产注册方法。*/ASSET_TYPES.forEach(type=>{Vue[type]=function(id:string,definition:Function|Object):Function|Object|void{if(!definition){returnthis.options[type+'s'][id]}else{/*伊斯坦布尔忽略if*/if(process.env.NODE_ENV!=='production'&&type==='component'){validateComponentName(id)}if(type==='component'&&isPlainObject(definition)){definition.name=definition.name||id定义=this.options。_base.extend(定义)}if(type==='directive'&&typeofdefinition==='function'){definition={bind:definition,update:definition}}this.options[type+'s'][id]=definitionreturndefinition}}})}从这里可以看出,Vue.component、Vue.directive和Vue.filter都是共享一套代码的,而我们这里只关心Vue.component。先看函数的入参,根据文档,Vue.component的第一个参数id是组件名,第二个参数定义可以是一个option对象,也可以是一个构造函数。然后看这段代码:if(type==='component'&&isPlainObject(definition)){definition.name=definition.name||iddefinition=this.options._base.extend(definition)}这段代码的意思是如果Vue.component传入一个option对象,然后调用extend方法将其转化为构造函数,与官方文档描述一致.然后这段代码将构造函数挂载到Vue.options:this.options[type+'s'][id]=definition挂载完成后,你应该得到以下结果:Vue.options={components:{/*SomeVue内置的组件,比如keep-alive,也会挂载在这里*/'custom-component':VueComponent(options)},directives:{},filters:{}}这里的答案应该很清楚了,Vue.component通过将自定义组件挂载到Vue.options.components来实现全局注册。参考Vue.component-Vue官方文档