1. 钩子函数
通过该钩子函数,可以让使用者在vue的生命周期的不同阶段去执行对应的方法以及逻辑,根据传入的字符串hook,并在vm.$options中获取对应的回调函数数组,并遍历执行
export function callHook (vm: Component, hook: string) {
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()
}
2. 生命周期中的钩子
2.1. beforeCreate和created
源码中,beforeCreate在initState之前调用,
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')
initState中初始化props、methods、data、computed、watch等属性,故这些属性中的值在beforeCreate钩子中无法获取。created钩子中可以访问props、data、methods等属性
export function initState (vm: Component) {
vm._watchers = []
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)
}
if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch)
}
}
2.2. beforeMount 和 mounted
created之后就是挂载,vm.$mount(vm.$options.el),其中,在$mount中调用了mountComponent方法,beforeMount是在mountComponent方法中调用的。执行完beforeMount钩子,会执行vm._render(),通过_render()方法获取vnode,然后执行vm._update()方法进行vnode的更新,更新完会挂载mounted钩子。
export function mountComponent (
vm: Component,
el: ?Element,
hydrating?: boolean
): Component {
...
callHook(vm, 'beforeMount')
let updateComponent
...
updateComponent = () => {
vm._update(vm._render(), hydrating)
}
new Watcher(vm, updateComponent, noop, {
before () {
if (vm._isMounted && !vm._isDestroyed) {
callHook(vm, 'beforeUpdate')
}
}
}, true /* isRenderWatcher */)
...
if (vm.$vnode == null) {
vm._isMounted = true
callHook(vm, 'mounted')
}
return vm
}
2.3. beforeUpdate 和 updated
上面代码中的new Watcher()为渲染watcher。若是第一次初始化组件,因组件未挂载,vm._isMounted为false,并不会执行beforeUpdate钩子。当组件需要更新时,会执行beforeUpdate钩子。组件更新完之后会调用updated钩子
2.4. beforeDestroy 和 destroyed
vm._update()方法更新vnode的时候,将$destroy方法挂载到Vue的原型上,如下所示。
当组件开始销毁时,会调用beforeDestroy钩子。接着会将自身从父组件中删除,销毁watcher,并将当前的vnode进行销毁。销毁之后调用destroyed钩子
Vue.prototype.$destroy = function () {
const vm: Component = this
if (vm._isBeingDestroyed) {
return
}
callHook(vm, 'beforeDestroy')
vm._isBeingDestroyed = true
// remove self from parent
const parent = vm.$parent
if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
remove(parent.$children, vm)
}
// teardown watchers
if (vm._watcher) {
vm._watcher.teardown()
}
let i = vm._watchers.length
while (i--) {
vm._watchers[i].teardown()
}
// remove reference from data ob
// frozen object may not have observer.
if (vm._data.__ob__) {
vm._data.__ob__.vmCount--
}
// call the last hook...
vm._isDestroyed = true
// invoke destroy hooks on current rendered tree
vm.__patch__(vm._vnode, null)
// fire destroyed hook
callHook(vm, 'destroyed')
// turn off all instance listeners.
vm.$off()
// remove __vue__ reference
if (vm.$el) {
vm.$el.__vue__ = null
}
// release circular reference (#6759)
if (vm.$vnode) {
vm.$vnode.parent = null
}
}
}
3. 每个生命周期中可以做哪些事情?
created:可以获取data,props,methods等属性,可以发送资源请求 mounted:此时dom已经挂载完成,可以对dom进行操作 destroyed: 可以在这个钩子中清楚定时器以及事件绑定