1.8 生命周期钩子函数的合并

在学习Vue时,有一个重要的思想,生命周期。它是我们使用Vue高效开发组件的基础,我们可以在组件实例的不同阶段去定义需要执行的函数,让组件的功能更加丰富。在介绍生命周期钩子函数的选项合并前,我们有必要复习以下官方的生命周期图。

1.8 生命周期钩子函数的合并 - 图1

然而从源码中我们可以看到Vue的生命周期钩子不止这些,它有多达12个之多,每个钩子的执行时机我们暂且不深究,它们会在以后的章节中逐一出现。我们关心的是:子父组件的生命周期钩子函数是遵循什么样的规则合并。

  1. var LIFECYCLE_HOOKS = [
  2. 'beforeCreate',
  3. 'created',
  4. 'beforeMount',
  5. 'mounted',
  6. 'beforeUpdate',
  7. 'updated',
  8. 'beforeDestroy',
  9. 'destroyed',
  10. 'activated',
  11. 'deactivated',
  12. 'errorCaptured',
  13. 'serverPrefetch'
  14. ];
  15. LIFECYCLE_HOOKS.forEach(function (hook) {
  16. strats[hook] = mergeHook; // 对生命周期钩子选项的合并都执行mergeHook策略
  17. });

mergeHook是生命周期钩子合并的策略,简单的对代码进行总结,钩子函数的合并原则是:

  1. 如果子类和父类都拥有相同钩子选项,则将子类选项和父类选项合并。
  2. 如果父类不存在钩子选项,子类存在时,则以数组形式返回子类钩子选项。
  3. 当子类不存在钩子选项时,则以父类选项返回。
  4. 子父合并时,是将子类选项放在数组的末尾,这样在执行钩子时,永远是父类选项优先于子类选项执行。
  1. // 生命周期钩子选项合并策略
  2. function mergeHook (
  3. parentVal,
  4. childVal
  5. ) {
  6. // 1.如果子类和父类都拥有钩子选项,则将子类选项和父类选项合并,
  7. // 2.如果父类不存在钩子选项,子类存在时,则以数组形式返回子类钩子选项,
  8. // 3.当子类不存在钩子选项时,则以父类选项返回。
  9. var res = childVal ? parentVal ? parentVal.concat(childVal) : Array.isArray(childVal) ? childVal : [childVal] : parentVal;
  10. return res
  11. ? dedupeHooks(res)
  12. : res
  13. }
  14. // 防止多个组件实例钩子选项相互影响
  15. function dedupeHooks (hooks) {
  16. var res = [];
  17. for (var i = 0; i < hooks.length; i++) {
  18. if (res.indexOf(hooks[i]) === -1) {
  19. res.push(hooks[i]);
  20. }
  21. }
  22. return res
  23. }

下面结合具体的例子看合并结果。

  1. var Parent = Vue.extend({
  2. mounted() {
  3. console.log('parent')
  4. }
  5. })
  6. var Child = Parent.extend({
  7. mounted() {
  8. console.log('child')
  9. }
  10. })
  11. var vm = new Child().$mount('#app');
  12. // 输出结果:
  13. parent
  14. child

简单总结一下:对于生命周期钩子选项,子类和父类相同的选项将合并成数组,这样在执行子类钩子函数时,父类钩子选项也会执行,并且父会优先于子执行。