Vue源码之生命周期

147 阅读2分钟

callHook

src/instance/lifecycle.js

根据传⼊的字符串 hook ,去拿到 vm.$options[hook] 对应的回调函数数组,然后遍历执⾏,执⾏的时候把 vm 作为函数执⾏的上下⽂。
因此 callhook 函数的功能就是调⽤某个⽣命周期钩⼦注册的所有回调函数。

beforeCreate & created

在初始化时 src/instance/init.js

beforeCreate 和 created 的钩⼦调⽤是在 initState 的前后, 在beforeCreate前确立了父子关系和添加事件等操作。initState初始化了 props 、 data 、 methods 、 watch 、 computed 等属性。那么显然 beforeCreate 的钩⼦函数就拿不到这些东西,而created就可以。在这俩个钩⼦函数执⾏的时候,并没有渲染 DOM,所以我们也访问不了DOM。

beforeMount & mounted

  1. 在挂载时 src/core/instance/lifecycle.js
  1. 子组件执行mounted时机 执行patch时 src/core/vdom/patch.js

在patch中通过createElm创建节点是传入了insertedVnodeQueue空数组。

  • createElm:如果遇见组件标签则创建组件初始化组件


组件初始化完后,这里可以清楚看到往insertedVnodeQueue数组中添加当前的组件vnode,因为是深度遍历执行所以insertedVnodeQueue中第一个vnode永远是子组件而往后才是子组件的父组件。

  • createElm:如果不是组件,创建完孩子节点后判断当前vnode是否存在data属性。如果存在执行invokeCreateHooks。

这里判断data中是否存在hook,如果存在并且存在insert钩子,则把当前的组件vnode插入到insertedVnodeQueue数组中。

  • path函数最后

在patch函数最后执行了invokeInsertHook函数,函数遍历insertedVnodeQueue数组执行组件的insert钩子。

  • 创建组件时插入的钩子insert src/core/vdom/create-component.js

可以看到当组件没有mounted时执行mounted钩子。

  • 结论:插入队列过程是先子后父,子会先插入队列中,后面才是父组件,所以beforeMounte是先父后子,Mounted执行顺序是先子后父

beforeUpdate & updated

beforeupdate src/core/instance/lifecycle.js

在组件挂载时创建了组件的渲染Watcher,beforeUpdate 的执⾏时机是在渲染 Watcher 的 before函数,这⾥有个判断,在组件已经 mounted 并且组件没有destroyed,才会去调⽤这个钩⼦函数。flushSchedulerQueue是在我们修改了值触发了setter,将值订阅的watcher丢入队列中最后遍历执行watcher.before()。

updated 数据变化时触发 src/core/observer/scheduler.js

update 的执⾏时机是在 flushSchedulerQueue 函数调⽤的时候,updatedQueu是wathcer 数组的拷贝副本,在 callUpdatedHooks 函数中,它对这些watcher进行遍历,只有满⾜当前 watcher 为渲染watcher以及组件已经 mounted并且组件没有destoryed 这三个条件,才会执⾏ updated 钩⼦函数。

beforeDestroy & destroyed

beforeDestory src/core/instance/lifecycle.js 先父后子

destory src/core/instance/lifecycle.js 先子后父

总结

结论:执行顺序

  • parent beforeCreate

  • parent created

  • parent beforeMount

  • child beforeCreate

  • child created

  • child beforeMount

  • child mounted

  • parent mounted

  • parent beforeDestroy

  • child beforeDestroy

  • child destroyed

  • parent destroyed