在Vue当中,hooks能够做为一种event,在Vue的源码当中,称之为hookEvent。javascript
<Table @hook:updated="handleTableUpdated"></Table>
有一个来自第三方的复杂表格组件,表格进行数据更新的时候渲染时间须要1s,因为渲染时间较长,为了更好的用户体验,我但愿在表格进行更新时显示一个loading动画。html
有一个粗暴的办法是直接修改这个组件的源码,利用beforeUpdate和updated来显示loading,可是这种办法很是很差java
总之,修改源码这个方案可行,可是很差,不优雅。
那么,有没有办法,能够声明式的在模板上直接给一个组件注入一个生命周期函数呢?实际上是能够的,就是经过hookEvent。ide
所谓生命周期函数,就是在某一个特定的时间点调用的函数,因此咱们须要关注两件事:一、注册,二、调用。函数
咱们首先从调用开始。测试
vm._self = vm initLifecycle(vm) initEvents(vm) initRender(vm) callHook(vm, 'beforeCreate') initInjections(vm) // resolve injections before data/props initState(vm) initProvide(vm) // resolve provide after data/props callHook(vm, 'created')
上面是一段Vue的源码,能够看出,生命周期函数是经过callHook这个函数去调用的,天然而然,咱们去看看callHook函数的代码动画
export function callHook (vm: Component, hook: string) { // #7573 disable dep collection when invoking lifecycle hooks pushTarget() const handlers = vm.$options[hook] // 选项当中的生命周期函数 const info = `${hook} hook` if (handlers) { for (let i = 0, j = handlers.length; i < j; i++) { invokeWithErrorHandling(handlers[i], vm, null, vm, info) } } if (vm._hasHookEvent) { vm.$emit('hook:' + hook) } popTarget() }
因此,callHook('created')在vm._hasHookEvent为true的状况下,会执行$emit('hooks:created'),也就是说,一个有着 hook: 特殊前缀的事件,会在对应的生命周期当中执行。其实到这里,咱们已经能够大胆推断了:只要使用相似@hooks:created这个形式,就能够从Vue的模板中声明式的注入一个生命周期函数,测试一下,it works.this
<Table @hook:updated="handleTableUpdated"></Table>
以前的大胆推断,忽略了一个条件,那就是_hasHookEvent必需为true,接下来就去看看这个_hasHookEventprototype
const hookRE = /^hook:/ // 以hook:开头 Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component { const vm: Component = this if (Array.isArray(event)) { for (let i = 0, l = event.length; i < l; i++) { vm.$on(event[i], fn) } } else { (vm._events[event] || (vm._events[event] = [])).push(fn) // optimize hook:event cost by using a boolean flag marked at registration // instead of a hash lookup if (hookRE.test(event)) { vm._hasHookEvent = true } } return vm }
当使用了$on方法监听事件时,若是事件名以 hooks: 做为前缀,那么这个事件会被当作hookEvent,注册事件回调的同时,vm._hasHookEvent会被置为true,当使用callHook调用生命周期函数时,因为_hasHookEvent为true,因此会$emit('hooks:xxx'),注册的生命周期函数就会执行。code
因此,若是你想给一个Vue组件添加生命周期函数有3个办法: