Vue生命周期函数解析及各个组件间调用顺序

Vue生命周期函数

beforeCreate created beforeMount mounted beforeUpdate updated beforeDestroy destroyed

beforeCreate: 实例对象刚通过new Vue创建成功,props、methods、data、computed、watch都不可以使用,$el 属性为null

created: 实例初始化完成,props、methods、data、computed、watch都可以使用,虽然DOM还未挂载,$el为null,$ref为空数组,但已经开始监测data中数据的变化了,如果要在created函数中操作DOM,需要将操作都放在 Vue.nextTick() 的回调函数中

beforeMount: 还未挂载到DOM,render函数会被调用,即会找到对应的template模板,并编译成render函数,数据data虽初始化完成,但对于模板中的响应式变量还未替换成data中的数据如:{{name}},这就是虚拟DOM技术

mounted: el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子,$ref可以访问,网络请求可放到这里,注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted:

 mounted: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been rendered
  })
}

beforeUpdate: 数据更新前调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器

updated: 数据更新完成后执行,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之,
注意 updated 不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉 updated

  updated: function () {
    this.$nextTick(function () {
      // Code that will run only after the
      // entire view has been re-rendered
    })
  }

activated: 组件激活时调用

deactivated: 组件停用时调用

beforeDestroy: 实例销毁之前调用。在这一步,实例仍然完全可用。这里适合清除定时器等操作

destroyed: 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁

errorCaptured: 当父组件捕获一个来自子孙组件的错误时才会被调用,当errorHandler返回false时,会阻止错误继续向上传播,config.errorHandler也就不会调用

生命周期调用顺序

首先分别定义了三个组件test1、test2、test3,每个组件生命周期函数都有log打印及组件内的导航守卫log打印,值得注意的是,在test2组件中,又引入两个子组件,在子组件中也分别有生命周期和组件内导航守卫的log打印,如:

  

首次打开test1生命周期调用顺序

  test1-beforeRouteEnter -> test1-beforeCreate -> test1-created -> test1-beforeMount -> test1-mounted

test1跳转到test2生命周期调用顺序

  test1-beforeRouteLeave ->
   test2-beforeRouteEnter -> test2-beforeCreate -> test2-created -> test2-beforeMount ->
    zi1-beforeCreate -> zi1-created -> zi1-beforeMount ->
     zi2-beforeCreate -> zi2-created -> zi2-beforeMount ->
      test1-beforeDestroy -> test1-destroyed ->
       zi1-mounted -> zi2-mounted -> test2-Mounted

可以看出

  • 组件内导航守卫的执行顺序是优先于生命周期执行的
  • 子组件内的导航守卫函数是不执行的
  • 前一个组件销毁的两个生命周期函数是在跳转后组件的beforeMount后执行的
  • test2中多个子组件生命周期执行顺序是根据引入顺序执行的

test2跳转到test3生命周期调用顺序

  test2-beforeRouteLeave ->
   test3-beforeRouteEnter -> test3-beforeCreate -> test3-created -> test3-beforeMount ->
    test2-beforeDestroy ->
     zi1-beforeDestroy -> zi1-destroyed ->
      zi2-beforeDestroy -> zi2-destroyed ->
       test2-destroyed -> test3-mounted

可以看出

  • beforeDestroy函数是先执行父组件,然后再根据引入顺序分别执行子组件的beforeDestroy、destroyed,然后再执行父组件的destroyed
  • 子组件内的导航守卫函数是不执行的

test3跳转到test1生命周期调用顺序

  test3-beforeRouteLeave ->
   test1-beforeRouteEnter -> test1-beforeCreate -> test1-created -> test1-beforeMount ->
    test3-beforeDestroy -> test3-destroyed ->
     test1-mounted

keep-alive使用

引用官网

包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 相似, 是一个抽象组件:
它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。
当组件在 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。主要用于保留组件状态或避免重新渲染

keep-alive使用

1:在router中给每一个路由配置上keepAlive属性

需要缓存keepAlive值为true,不需要则设置为false,这里把test5设置成缓存组件

  {
      path: '/test4',
      name: 'test4',
      meta: {
          keepAlive: false,
      },
      component: () => import(/* webpackChunkName: "test" */ './views/test/test4.vue')
  },{
      path: '/test5',
      name: 'test5',
      meta: {
          keepAlive: true,
      },
      component: () => import(/* webpackChunkName: "test" */ './views/test/test5.vue')
  },{
      path: '/test6',
      name: 'test6',
      meta: {
          keepAlive: false,
      },
      component: () => import(/* webpackChunkName: "test" */ './views/test/test6.vue')
  }
2:修改App.vue组件的template模板

需要缓存就用keep-alive包裹,不需要则不包裹

  

有keep-alive组件生命周期调用顺序

首先分别定义了三个组件test4、test5、test6,每个组件生命周期函数都有log打印及组件内的导航守卫log打印,值得注意的是,在test5组件中,又引入两个子组件,在子组件中也分别有生命周期和组件内导航守卫的log打印,同时test5设置keepAlive为true

首次打开test4生命周期调用顺序

  test4-beforeRouteEnter -> test4-beforeCreate -> test4-created -> test4-beforeMount -> test4-mounted

test4跳转到test5生命周期调用顺序

  test4-beforeRouteLeave ->
   test5-beforeRouteEnter ->
    test4-beforeDestroy -> test4-destroyed ->
     test5-beforeCreate -> test5-created -> test5-beforeMount ->
      zi1-beforeCreate -> zi1-created -> zi1-beforeMount ->
       zi2-beforeCreate -> zi2-created -> zi2-beforeMount ->
        zi1-mounted -> zi2-mounted -> test5-mounted ->
         zi1-activated -> zi2-activated -> test5-activated

可以看出

  • 组件内导航守卫的执行顺序是优先于生命周期执行的
  • 子组件内的导航守卫函数是不执行的
  • test2中多个子组件生命周期执行顺序是根据引入顺序执行的
  • test2中activated函数是在mounted函数后执行,并且先执行子组件后执行父组件
  • 和不加keepAlive不同的是:前一个组件先执行销毁函数,再执行跳转后组件的各个生命周期

test5跳转到test6生命周期调用顺序

  test5-beforeRouteLeave ->
   test6-beforeRouteEnter -> test6-beforeCreate -> test6-created -> test6-beforeMount -> test6-mounted
     zi1-deactivated -> zi2-deactivated -> test5-deactivated

可以看出

  • test5组件被缓存了,不再执行销毁函数,同时test5的deactivated函数在跳转后组件的mounted函数后执行
  • 子组件内的导航守卫函数是不执行的

test6跳转到test4生命周期调用顺序

  test6-beforeRouteLeave ->
   test4-beforeRouteEnter -> test4-beforeCreate -> test14-created -> test4-beforeMount ->
    test6-beforeDestroy -> test6-destroyed ->
     test4-mounted

可以看出

因为test6和test4的keepAlive都为false,都不缓存组件,所以生命周期是先执行到test4的beforeMount函数,然后再销毁test6组件,然后再执行test4的mounted函数

test4跳转到test5生命周期调用顺序

  test4-beforeRouteLeave ->
   test5-beforeRouteEnter ->
    test4-beforeDestroy -> test4-destroyed ->
     zi1-activated -> zi2-activated -> test5-activated

可以看出
因为test5在之前已经缓存了,所以这次进入只调用activated函数

你可能感兴趣的:(前端,Vue生命周期函数详解,组件间生命周期调用顺序,keep-alive使用)