目录
4.使用keep-alive场合时,进入某个页面两次触发的生命周期
1. 路由器生命周期(思维导图我大致画了一下)
1. beforeRouteLeave => 2. beforeEach => 3. beforeRouteUpdate => 4. beforeEnter =>
5. beforeRouteEnter => 6.beforeResolve => 7.afterEach
(组件路由:1,3,5 独享路由:4 全局路由:2,6,7)
路由的钩子函数,根据配置的地方不同,大致分为三种
第一种:全局路由 包含:
全局前置防守:router.beforeEach,(每次路由跳转前的处理,可以用来判断当前用户是否在登录状态,开始进度条等...)
全局解析守卫:router.beforeResolve,(每次路由跳转完毕的处理,可以用来结束进度条等...)
全局后置防守:router.afterEach,(每次路由跳转完毕的处理,可以用来结束进度条等...)
第二种:独享路由 包含
独享路由防守:beforeEnter (在进入路由时触发)
第三种:组件路由 包含
组件路由:beforeRouteEnter(在渲染该组件的对应路由被验证前触发)
组件路由:beforeRouteUpdate (在当前路由改变,但是该组件被复用时调用)
组件路由:beforeRouteLeave(在导航离开渲染该组件的对应路由时调用)
注意:在使用的过程中,如果发现路由卡住不动的情况下,仔细检查 next 的操作
拿 beforeEnter 举例,如果你配置了 beforeEnter ,就需要设置 next() ,让它有个出口,不然它就卡住了
注意:beforeEach 里可能会因为你的写法问题,陷入无限循环,请仔细检查,确保 next 在任何情况下严格调用一次,if判断时,需严格加上else
全局路由:
import NProgress from 'nprogress' // Progress 进度条
import { getToken } from '@/utils/auth' // 验权
import router from './router'
/*
* 确保 next 在任何给定的导航守卫中都被严格调用一次。
* 它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,
* 否则钩子永远都不会被解析或报错。
*/
router.beforeEach((to, from, next)=>{
// 进度条开始
NProgress.start()
// 判断 token 是否存在
if(getToken()){
next()
}else{
next('/login')
}
})
/*
* beforeResolve 与 beforeEach 类似
* 官方说明:它在 每次导航时都会触发,但是确保在导航被确认之前
* 同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被正确调用。
*/
router.beforeResolve((to, from, next)=>{
console.log(' wosjio ')
})
/*
* 这个钩子不会接受 next 函数也不会改变导航本身
*/
router.afterEach((to, from) => {
// 进度条结束
NProgress.done()
})
独享路由:
/*
* 直接在路由配置上定义守卫
* 只在进入路由时触发,(它们只有在 从一个不同的 路由导航时,才会被触发)。
*/
{
path: 'password',
name: 'password',
component: () => import('@/views/pms/publisherInfo/password'),
meta: {
title: '密码管理',
keepAlive: true
},
hidden: true,
beforeEnter: (to, from, next) => {
console.log('my is beforeEnter')
next()
},
},
组件路由:
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被验证前调用
// 不能获取组件实例 `this` !
// 因为当守卫执行时,组件实例还没被创建!
console.log('my is beforeRouteEnter')
next(vm => {
// 通过 `vm` 访问组件实例
console.log(vm.text)
})
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
console.log('my is beforeRouteUpdate')
next()
},
beforeRouteLeave(to, from, next) {
// 在导航离开渲染该组件的对应路由时调用
// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
console.log('my is beforeRouteLeave')
next()
},
2.单组件生命周期
单组件页面加载时触发四个钩子 依次顺序:
beforeUpdate => updated => beforeMount => mounted
单组件页面改动时触发钩子:
beforeUpdate => updated
单组件页面离开时触发两个钩子 依次顺序:
beforeDestroy => deactivated
3.父子组件嵌套生命周期
父子组件嵌套页面加载时触发八个钩子 依次顺序:
父组件 beforeUpdate => 父组件 updated => 父组件 beforeMount =>
子组件 beforeUpdate => 子组件 updated => 子组件 beforeMount => 子组件 mounted=> 父组件 mounted
父组件最后完成加载
父子组件嵌套页面改动时触发钩子:
修改哪个组件里的数据,就触发哪个组件内的 beforeUpdate => updated
父子组件嵌套页面离开时触发四个钩子 依次顺序:
父组件 beforeDestroy => 子组件 beforeDestroy => 子组件 deactivated => 父组件 deactivated
父组件最后完成销毁
4.使用keep-alive场合时,进入某个页面两次触发的生命周期
第一次进入 a 触发钩子:
[a] beforeCreate => [a] created => [a] beforeMount => [a] mounted => [a] activated
跳转至 b 触发钩子:
[b] beforeCreate => [b] created => [b] beforeMount => [a] deactivated => [b] mounted => [b] activated
第二次进入 a:
[a] activated
5.实际使用场景
created:摘取路由上的参数,发送请求
mounted:获取 DOM
nextTick:数据更新后的立即执行 操作DOM相关业务
updated:任何数据的更新,如果要做统一的业务逻辑处理
beforeUpdate:编辑的数据还没有保存,询问用户是否保存后再退出当前页面
watch:监听具体数据变化,并做相应的处理
beforeCreate() {
/*
* 在实例初始化之后,数据观测和事件配置之前被调用,
* 此时组件的选项对象还未创建,el 和 data 并未初始化,
* 因此无法访问methods, data, computed等上的方法和数据。
*/
console.log('my is beforeCreate')
},
created() {
/*
* 实例已经创建完成之后被调用,在这一步,实例已完成以下配置:数据观测、属性和方法的运算,watch/event事件回调,完成了data 数据的初始化,
* 在这里可以进行调用data数据,以及方法,发送ajax一些操作
*/
console.log('created')
},
beforeMount() {
/*
* DOM 渲染之前被调用,并且开始通过 render 建立虚拟 DOM
*/
console.log('beforeMount')
},
mounted() {
/*
* DOM 渲染完成被调用,这时页面已经渲染完毕
* 可以通过 ref 获取页面元素的 DOM 了
*/
console.log('mounted')
},
beforeUpdate(){
/*
* 数据更新前被调用
* data 数据有更新时,内存中重新编译了最新模板字符串,但还未重新渲染DOM
*/
console.log('beforeUpdate')
},
updated() {
/*
* 数据更新完成后被调用
* 已经重新渲染 DOM ,这时你可以继续操作 DOM
*/
console.log('updated')
},
beforeDestroy() {
/*
* 实例销毁之前调用
* 这时date内数据以及方法,过滤器等依然还可以使用
*/
console.log('beforeDestroy')
},
destroyed() {
/*
* 实例销毁完成后调用
* 实例的所有东西都会解绑销毁
*/
console.log('deactivated')
},
欢迎同学们发表评论!