Vue 2.6源码学习(06)-Vue.directive,Vue.filter,Vue.component

157 阅读2分钟

主要介绍Vue.directive,Vue.filter,Vue.component使用和原理

1.Vue.directive( id, [definition] )

// 注册\
Vue.directive('my-directive', {
bind: function () {},
inserted: function () {},
update: function () {},
componentUpdated: function () {},
unbind: function () {}
})

// 注册 (指令函数)
Vue.directive('my-directive', function () {
// 这里将会被 `bind` 和 `update` 调用
})

2. Vue.filter( id, [definition] )

// 注册
Vue.filter('my-filter', function (value) {
// 返回处理后的值
})

// getter,返回已注册的过滤器
var myFilter = Vue.filter('my-filter')

3.Vue.component( id, [definition] )

// 注册组件,传入一个扩展过的构造器
Vue.component('my-component', Vue.extend({ /* ... */ }))

// 注册组件,传入一个选项对象 (自动调用 Vue.extend)
Vue.component('my-component', { /* ... */ })

// 获取注册的组件 (始终返回构造器)
var MyComponent = Vue.component('my-component')

源码

Vue.directive,Vue.filter,Vue.component在源码里是使用同一个方法来实现的。

/**
 * const ASSET_TYPES = [
  'component',
  'directive',
  'filter'
]
*/
function initAssetRegisters (Vue: GlobalAPI) {
  /**
   * Create asset registration methods.
   */
  ASSET_TYPES.forEach(type => {
    Vue[type] = function (
      id: string,
      definition: Function | Object
    ): Function | Object | void {
      if (!definition) {
        //如果没有第二个参数,就直接返回已经保存的
        return this.options[type + 's'][id]
      } else {
        /* istanbul ignore if */
        if (process.env.NODE_ENV !== 'production' && type === 'component') {
          validateComponentName(id)//这里校验组件的名称是否符合规范
        }
        if (type === 'component' && isPlainObject(definition)) {
          definition.name = definition.name || id
          definition = this.options._base.extend(definition)//_base是Vue
        }
        if (type === 'directive' && typeof definition === 'function') {
          //指令的处理,添加bind,update
          definition = { bind: definition, update: definition }
        }
        //做缓存
        this.options[type + 's'][id] = definition
        return definition
      }
    }
  })
}

在这里初始化

function initGlobalAPI (Vue: GlobalAPI) {
  // config
  const configDef = {}
  configDef.get = () => config
  if (process.env.NODE_ENV !== 'production') {
    configDef.set = () => {
      warn(
        'Do not replace the Vue.config object, set individual fields instead.'
      )
    }
  }
  Object.defineProperty(Vue, 'config', configDef) // 配置信息

  // exposed util methods.
  // NOTE: these are not considered part of the public API - avoid relying on
  // them unless you are aware of the risk.
  Vue.util = { // Vue中的工具方法
    warn,
    extend, // 合并
    mergeOptions, // 合并策略
    defineReactive // 定义响应式
  }

  Vue.set = set // set 
  Vue.delete = del // delete
  Vue.nextTick = nextTick

  // 2.6 explicit observable API
  Vue.observable =(obj: T): T => { // 让一个对象变成了响应式的
    observe(obj)
    return obj
  }

  Vue.options = Object.create(null)
    //初始化components,directives,filter
  // Vue.options.components = {}
  // Vue.options.directives = {}
  // Vue.options.filter = {}
  ASSET_TYPES.forEach(type => {
    Vue.options[type + 's'] = Object.create(null)
  })

  // this is used to identify the "base" constructor to extend all plain-object
  // components with in Weex's multi-instance scenarios.
  Vue.options._base = Vue // _base 指定的永远是Vue的构造函数

  extend(Vue.options.components, builtInComponents) //keep-alive的实现

  initUse(Vue) // Vue.use
  initMixin(Vue) // Vue.mixin
  initExtend(Vue) // Vue.extend
  initAssetRegisters(Vue) // 实现 Vue.component Vue.directive Vue.filter
}

小结

记录学习Vue2源码,下一期学习keep-alive。