页面加载时,vue生命周期的触发顺序
首先思考在进入组件时会触发的周期:
- 根实例的加载相关的生命周期(beforeCreate、created、beforeMount、mounted)
- 组件实例的加载相关的生命周期(beforeCreate、created、beforeMount、mounted)
- 全局路由钩子(router,beforeEach)
- 组件路由钩子(beforeRouteEnter)
- 组件路由钩子的next里的回调(beforeRouteEnter)
- 指令的周期(bind、inserted)
- 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>
可以看到执行的顺序为:
- 路由钩子(beforeEach、beforeRouteEnter、afterEach)
- 根组件(beforeCreate、created、beforeMount)
- 组件(beforeCreate、created、beforeMount)
- 指令(bind、inserted)
- 组件 mounted
- 根组件 mounted
- beforeRouteEnter的next的回调
- nextTick
结论:
具体顺序:router.beforeEach > beforeRouteEnter > router.afterEach
在进行路由拦截的时候要避免使用实例内部的方法或属性。 在开发项目时候,把具体拦截的程序,写在根实例的方法上,到beforeEach去调用会导致整个拦截的周期,推迟到实例渲染之后。 因此对于一些路由组件的beforeRouteEnter里的请求并无法拦截,页面看上去已经拦截下来了,实际上请求依然发了出去,beforeRouteEnter内的函数依然执行了。