• vue生命周期函数源码


      

    callHook 函数的逻辑很简单,根据传入的字符串 hook,去拿到 vm.$options[hook] 对应的回调函数数组,然后遍历执行,执行的时候把 vm 作为函数执行的上下文。

    各个阶段的生命周期的函数也被合并到 vm.$options 里,并且是一个数组。因此 callhook 函数的功能就是调用某个生命周期钩子注册的所有回调函数。

    function callHook (vm, hook) {
        // #7573 disable dep collection when invoking lifecycle hooks
        pushTarget();
        var handlers = vm.$options[hook];
        var info = hook + " hook";
        if (handlers) {
          for (var i = 0, j = handlers.length; i < j; i++) {
            invokeWithErrorHandling(handlers[i], vm, null, vm, info);
          }
        }
        if (vm._hasHookEvent) {
          vm.$emit('hook:' + hook);
        }
        popTarget();
      }

    beforeCreate 和 created 函数都是在实例化 Vue 的阶段, _init 方法中执行的

    可以看到 beforeCreate 和 created 的钩子调用是在 initState 的前后,initState 的作用是初始化 propsdatamethodswatchcomputed 等属性。

    那么显然 beforeCreate 的钩子函数中就不能获取到 propsdata 中定义的值,也不能调用 methods 中定义的函数。

    在这俩个钩子函数执行的时候,并没有渲染 DOM,所以我们也不能够访问 DOM,一般来说,如果组件在加载的时候需要和后端有交互,

    放在这俩个钩子函数执行都可以,如果是需要访问 propsdata 等数据的话,就需要使用 created 钩子函数。

    Vue.prototype._init = function (options?: Object) {
      // ...
      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')
      // ...
    }

    在执行 vm._render() 函数渲染 VNode 之前,执行了 beforeMount 钩子函数,在执行完 vm._update() 把 VNode patch 到真实 DOM 后,执行 mouted 钩子。

    注意,这里对 mouted 钩子函数执行有一个判断逻辑,vm.$vnode 如果为 null,则表明这不是一次组件的初始化过程,而是我们通过外部 new Vue 初始化过程

    export function mountComponent (
      vm: Component,
      el: ?Element,
      hydrating?: boolean
    ): Component {
      vm.$el = el
      // ...
      callHook(vm, 'beforeMount')
    
      let updateComponent
      /* istanbul ignore if */
      if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
        updateComponent = () => {
          const name = vm._name
          const id = vm._uid
          const startTag = `vue-perf-start:${id}`
          const endTag = `vue-perf-end:${id}`
    
          mark(startTag)
          const vnode = vm._render()
          mark(endTag)
          measure(`vue ${name} render`, startTag, endTag)
    
          mark(startTag)
          vm._update(vnode, hydrating)
          mark(endTag)
          measure(`vue ${name} patch`, startTag, endTag)
        }
      } else {
        updateComponent = () => {
          vm._update(vm._render(), hydrating)
        }
      }
    
      // we set this to vm._watcher inside the watcher's constructor 
      // since the watcher's initial patch may call $forceUpdate (e.g. inside child
      // component's mounted hook), which relies on vm._watcher being already defined
      new Watcher(vm, updateComponent, noop, {
        before () {
          if (vm._isMounted) {
            callHook(vm, 'beforeUpdate')
          }
        }
      }, true /* isRenderWatcher */)
      hydrating = false
    
      // manually mounted instance, call mounted on self
      // mounted is called for render-created child components in its inserted hook
      if (vm.$vnode == null) {
        vm._isMounted = true
        callHook(vm, 'mounted')
      }
      return vm
    }
        

    VNode patch 到 DOM 后,会执行 invokeInsertHook 函数,把 insertedVnodeQueue 里保存的钩子函数依次执行一遍

    function invokeInsertHook (vnode, queue, initial) {
          // delay insert hooks for component root nodes, invoke them after the
          // element is really inserted
          if (isTrue(initial) && isDef(vnode.parent)) {
            vnode.parent.data.pendingInsert = queue;
          } else {
            for (var i = 0; i < queue.length; ++i) {
              queue[i].data.hook.insert(queue[i]);
            }
          }
        }
  • 相关阅读:
    singleton模式 在软件开发中的运用
    State Pattern
    闲话闲说——关于异常
    程序人生
    Event
    SerialPort实现modem的来电显示
    利用枚举进行状态的设计
    职责链模式的运用
    我对当前项目的一些看法
    SHAREPOINT 2007 网站模板(解决方案)安装和卸载
  • 原文地址:https://www.cnblogs.com/TTblog5/p/12869258.html
Copyright © 2020-2023  润新知