5.1 组件两种注册方式

熟悉Vue的开发流程的都知道,Vue组件在使用之前需要进行注册,而注册的方式有两种,全局注册和局部注册。在进入源码分析之前,我们先回忆一下两者的用法,以便后续掌握两者的差异。

5.1.1 全局注册

  1. Vue.component('my-test', {
  2. template: '<div>{{test}}</div>',
  3. data () {
  4. return {
  5. test: 1212
  6. }
  7. }
  8. })
  9. var vm = new Vue({
  10. el: '#app',
  11. template: '<div id="app"><my-test><my-test/></div>'
  12. })

其中组件的全局注册需要在全局实例化Vue前调用,注册之后可以用在任何新创建的 Vue 实例的模板中调用。

5.1.2 局部注册

  1. var myTest = {
  2. template: '<div>{{test}}</div>',
  3. data () {
  4. return {
  5. test: 1212
  6. }
  7. }
  8. }
  9. var vm = new Vue({
  10. el: '#app',
  11. component: {
  12. myTest
  13. }
  14. })

当只需要在某个局部用到某个组件时,可以使用局部注册的方式进行组件注册,此时局部注册的组件只能在注册该组件的组件内部使用。

5.1.3 注册过程

简单回顾两种组件注册方式后,我们来看注册过程到底发生了什么,我们以全局组件注册为例。它通过Vue.component(name, {…})进行组件注册,Vue.component的定义在Vue源码的初始化中。

  1. // 初始化全局api
  2. initAssetRegisters(Vue);
  3. var ASSET_TYPES = [
  4. 'component',
  5. 'directive',
  6. 'filter'
  7. ];
  8. function initAssetRegisters(Vue){
  9. // 定义ASSET_TYPES中每个属性的方法,其中包括component
  10. ASSET_TYPES.forEach(function (type) {
  11. // type: component,directive,filter
  12. Vue[type] = function (id,definition) {
  13. if (!definition) {
  14. // 直接返回注册组件的构造函数
  15. return this.options[type + 's'][id]
  16. }
  17. ...
  18. if (type === 'component') {
  19. // 验证component组件名字是否合法
  20. validateComponentName(id);
  21. }
  22. if (type === 'component' && isPlainObject(definition)) {
  23. // 组件名称设置
  24. definition.name = definition.name || id;
  25. // Vue.extend() 创建子组件,返回子类构造器
  26. definition = this.options._base.extend(definition);
  27. }
  28. // 为Vue.options 上的component属性添加将子类构造器
  29. this.options[type + 's'][id] = definition;
  30. return definition
  31. }
  32. });
  33. }

源码中全局注册组件的实际是调用构造函数Vue的静态方法extend,并且为Vue.options 上的component属性添加子类构造器。其中extend方法的定义我们在深入剖析Vue源码 - 选项合并(上)中的子类构造器一段中有介绍这里不赘述,总结而言:Vue.extend创建了一个基于父Vue的子类,创建过程会继承父类的方法,并对父类子类的配置进行合并,最终返回一个子类的构造器。这个子组件的名称默认以Vue.component()的第一个参数作为组件名,当组件选项有name属性时,则用name属性覆盖。当Vue.component()不传递第二个选项参数时,会返回已经注册过的子类构造器。

接下来留下一个问题,局部注册和全局注册的在实现上的区别在哪里?