你真的了解Vue2.0的生命周期执行顺序吗?

2,395 阅读3分钟

最近面试遇到一个很有意思的问题:

你知道Vue的同一生命周期在子组件先执行还是父组件先执行?

可能了解Vue的执行机制的同学就已经知道答案了,不着急说答案,想请你慢慢看完。

我们来测试一下:

探索1:生命周期在平级子组件和父组件中的执行顺序

我们讲讲最重要的俩:created 和 mounted

我首先创建了两个子组件:CompOne 和 CompTwo,分别在两个组件中写入了mounted方法和created方法。

<template>
    <div>        
        <h2>子组件1</h2>    
    </div>
</template>
<script>    
    export default {
        mounted() {
            console.log("子组件1 —— mounted")
        },
        created() {
            console.log("子组件1 —— created")
        },
    }
</script>

<template>
    <div>
        <h2>子组件2</h2>
    </div>
</template>
<script>
    export default {
        mounted() {
            console.log("子组件2 —— mounted")
        },
        created() {
            console.log("子组件2 —— created")
        },
    }
</script>

接下来呢,我们把他引到父组件(App.vue)中来看看,当然,在父组件(App.vue)中也有created和mounted方法

<template>
  <div>
    123
    <CompOne></CompOne>
    <CompTwo></CompTwo>
  </div>
</template>
<script>
  import CompOne from "./views/CompOne"
  import CompTwo from "./views/CompTwo"
  export default {
    components:{
      CompOne, CompTwo
    },
    mounted() {
      console.log("App —— mounted")
    },
    created() {
      console.log("App —— created")
    },
  }
</script>

这时候我们来看看浏览器的输出结果:

结论:

  1. 不论子组件有多少,父组件的生命周期created总是先执行的,父组件的生命周期mounted总是最后一个执行的
  2. 平级各子组件的生命周期created是接下来执行的,然后是mounted

这里我引发了一个思考?

    ”调换下组件的位置看看执行结果会是什么样子的?

看好了,我调换了两个平级子组件的位置:

<template>
  <div>
    123
    <CompTwo></CompTwo>
    <CompOne></CompOne>
  </div>
</template>

看看结果:

结论:

平级子组件的同一生命周期执行顺序取决于子组件挂载在父组件中的位置!

探索2:生命周期在嵌套型组件中的执行顺序

嵌套型(就是俄罗斯套娃啦!)

上代码:

//这是第一层父组件(App.vue)
<template>
  <div>
    <h2>最大父组件(App.vue)</h2>
    <CompOne></CompOne>
  </div>
</template>
<script>
  import CompOne from "./views/CompOne"
  export default {
    components:{
      CompOne
    },
    mounted() {
      console.log("App —— mounted")
    },
    created() {
      console.log("App —— created")
    },
  }
</script>


//这是第二层父组件(CompOne.vue)
<template>
    <div>
        <h2>子组件1</h2>
        <CompTwo></CompTwo>
    </div>
</template>
<script>
    import CompTwo from "./CompTwo"
    export default {
        components:{ CompTwo },
        mounted() {
            console.log("子组件1 —— mounted")
        },
        created() {
            console.log("子组件1 —— created")
        },
    }
</script>

//这是第三层组件,也是最内的一层(CompTwo.vue)
<template>
    <div>
        <h2>子组件2</h2>
    </div>
</template>
<script>
    export default {
        mounted() {
            console.log("子组件2 —— mounted")
        },
        created() {
            console.log("子组件2 —— created")
        },
    }
</script>

来吧,看看结果,迫不及待~

请仔细看看输出结果,然后再看结论,给大脑一些思维时间 ~~~

结论:

不论子组件嵌套多少层,总是最外层(最大的父组件:App.vue)的生命周期created先执行,mounted最后执行,接下来便是向内一层(CompOne.vue)的生命周期created执行,接下来就是再向内一层(也就是第三层)的生命周期created执行,其次第三层的mounted执行,然后就是第二层的mounted了。

说的一大堆,给你看个输出图你就懂了:

是的,created生命周期又外到内一层层先执行,而mounted生命周期则由内到外接着一层层执行!

继续更新下~

今天有同学提议的”路由懒加载中生命周期执行顺序又会是怎样?“

探索3:路由懒加载中的平级子组件的生命周期执行顺序

首先定义好App.vue文件:

<template>
  <div>
    <router-view></router-view>
  </div>
</template>
<script>
  export default {
    mounted() {
      console.log("App —— mounted")
    },
    created() {
      console.log("App —— created")
    },
  }
</script>

父组件需要重新定义喽:

//CompMost.vue
<template>
    <div>
        <h2>最大父组件</h2>
        <CompOne></CompOne>
        <CompTwo></CompTwo>
    </div>
</template>
<script>
    import CompOne from "./CompOne"
    import CompTwo from "./CompTwo"
    export default {
        components: { CompOne, CompTwo },
        mounted() {
            console.log("Most —— mounted")
        },
        created() {
            console.log("Most —— created")
        },
    }
</script>

两个子组件依旧没有变动:

//CompOne组件
<template>
    <div>
        <h2>子组件1</h2>
    </div>
</template>
<script>
    export default {
        mounted() {
            console.log("子组件1 —— mounted")
        },
        created() {
            console.log("子组件1 —— created")
        },
    }
</script>

//CompTwo组件
<template>
    <div>
        <h2>子组件2</h2>
    </div>
</template>
<script>
    export default {
        mounted() {
            console.log("子组件2 —— mounted")
        },
        created() {
            console.log("子组件2 —— created")
        },
    }
</script>

router.js文件我就不写了,用的懒加载,来看看结果:

结论:
当采用路由懒加载的方式时候,App.vue中的生命周期created和mounted先执行,其余的跟之前一样

防止你模糊,附赠非懒加载的平级组件的生命周期执行顺序:

探索4:路由懒加载条件下嵌套型子组件的生命周期执行顺序

嵌套条件下(代码跟探索2中的一样),只是路由我们使用了懒加载

代码就省略喽,重复太多了,给你结果~

结论:
依旧App.vue文件中的生命周期created和mounted先执行,其余的依旧。

附赠非路由懒加载条件下嵌套型组建的生命周期执行顺序结果:

是的,跟探索2结论一样。

最终结论:
懒加载条件下,App.vue的生命周期会先执行(created和mounted),不论嵌套型还是平级的子组件。

最后,感谢热心同学,欢迎探讨~