Vue组件的生命周期

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

源码中,beforeCreateinitState之前调用,

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中初始化propsmethodsdatacomputedwatch等属性,故这些属性中的值在beforeCreate钩子中无法获取。created钩子中可以访问propsdatamethods等属性

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._isMountedfalse,并不会执行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: 可以在这个钩子中清楚定时器以及事件绑定

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享