主要介绍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。