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

    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

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