1. Hook functions

This hook function allows users to execute corresponding methods and logic at different stages of the vue life cycle, according to the string hook passed in, and obtain the corresponding callback function array in vm.$options, and iterate through the execution

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()
}
Copy the code

2. Hooks in the lifecycle

2.1. BeforeCreate and created

In the source code, beforeCreate is called before 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')
Copy the code

Properties such as props, methods, data, computed, and watch are initialized in initState, so the values in these properties cannot be retrieved from the beforeCreate hook. The created hook allows access to properties such as props, data, and 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) } }Copy the code

2.2. BeforeMount and mounted

Created is mounted, vm.$mount(vm.$options.el), where the mountComponent method is called in $mount and beforeMount is called in the mountComponent method. BeforeMount hooks are executed, vm._render() is executed, vnode is obtained using _render(), and vNode is updated using vm._update(). After updating vNode, mounted hooks are 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
}
Copy the code

2.3. BeforeUpdate and updated

The new Watcher() in the code above is the render Watcher. If the component is initialized for the first time, vm._isMounted is false and the beforeUpdate hook is not executed because the component is not mounted. The beforeUpdate hook is executed when a component needs to be updated. The updated hook is called after the component is updated

2.4. BeforeDestroy and destroyed

When the vm._update() method updates the VNode, mount the $destroy method to the prototype of the Vue, as shown below. The beforeDestroy hook is called when a component begins to destroy. It then removes itself from the parent component, destroys the Watcher, and destroys the current VNode. Call the Destroyed hook after destruction

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}}}Copy the code

3. What can be done in each lifecycle?

Mounted: Destroyed the timer and event binding on the DOM. Created: gets data, props, methods, and other properties. Creates: sends resource requests