vue页面加载时,生命周期的触发顺序

1,686 阅读1分钟

页面加载时,vue生命周期的触发顺序

首先思考在进入组件时会触发的周期:
  1. 根实例的加载相关的生命周期(beforeCreate、created、beforeMount、mounted)
  2. 组件实例的加载相关的生命周期(beforeCreate、created、beforeMount、mounted)
  3. 全局路由钩子(router,beforeEach)
  4. 组件路由钩子(beforeRouteEnter)
  5. 组件路由钩子的next里的回调(beforeRouteEnter)
  6. 指令的周期(bind、inserted)
  7. nextTick方法的回调
项目测试:

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

router.beforeEach((to, form, next) => {
  console.log('路由全局钩子:beforeEach');
  next();
})

router.afterEach((to,form)=>{
  console.log('路由全局钩子:afterEach');
})

Vue.config.productionTip = false

new Vue({
  beforeCreate(){
    console.log('根组件:beforeCreate')
  },
  created(){
    console.log('根组件:created')
  },
  beforeMount(){
    console.log('根组件:beforeMount')
  },
  mounted(){
    console.log('根组件:mounted')
  },
  router,
  store,
  render: h => h(App)
}).$mount('#app')

About.vue

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <p><button @click="$router.push('/')">(#^.^#)</button></p>
  </div>
</template>

<script>
export default {
  beforeRouteEnter(to,from,next){
    console.log('组件路由钩子:beforeRouteEnter');
    next(vm=>{
      console.log('组件路由钩子beforeRouteEnter的next')
    })
  },
  beforeCreate(){
    console.log('组件:beforeCreate')
  },
  created(){
    this.$nextTick(()=>{
      console.log('nextTick')
    })
    console.log('组件:created')
  },
  beforeMount(){
    console.log('组件:beforeMount')
  },
  mounted(){
    console.log('组件:mounted')
  },
  directives:{
    ooo:{
      bind(el,binding,vnode){
        console.log('指令binding')
      },
      inserted(el,binding,vnode){
        console.log('指令inserted')
      }
    }
  }
}
</script>

image.png

可以看到执行的顺序为:
  1. 路由钩子(beforeEach、beforeRouteEnter、afterEach)
  2. 根组件(beforeCreate、created、beforeMount)
  3. 组件(beforeCreate、created、beforeMount)
  4. 指令(bind、inserted)
  5. 组件 mounted
  6. 根组件 mounted
  7. beforeRouteEnter的next的回调
  8. nextTick

结论:

具体顺序:router.beforeEach > beforeRouteEnter > router.afterEach

在进行路由拦截的时候要避免使用实例内部的方法或属性。 在开发项目时候,把具体拦截的程序,写在根实例的方法上,到beforeEach去调用会导致整个拦截的周期,推迟到实例渲染之后。 因此对于一些路由组件的beforeRouteEnter里的请求并无法拦截,页面看上去已经拦截下来了,实际上请求依然发了出去,beforeRouteEnter内的函数依然执行了。

指令的绑定在组件mounted之前,组件的beforeMount之后。