vue生命周期探究(一)

vue官方文档---实例生命周期
vue-router2.3版文档---路由勾子
vue官方文档---指令及其绑定周期html

前言

在使用vue开发的过程当中,咱们常常会接触到生命周期的问题。那么你知道,一个标准的工程项目中,会有多少个生命周期勾子吗?让咱们来一块儿来盘点一下:vue

  1. 根组件实例:8个 (beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed)node

  2. 组件实例:8个 (beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed)ajax

  3. 全局路由钩子:2个 (beforeEach、afterEach)vue-router

  4. 组件路由钩子:3个 (beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave)segmentfault

  5. 指令的周期: 5个 (bind、inserted、update、componentUpdated、unbind)dom

  6. beforeRouteEnter的next所对应的周期ide

  7. nextTick所对应的周期函数

吓到了吗?合计居然一共有28个周期,是否看得头昏眼花了呢?接下来让咱们一块儿来介绍一下各个周期的一般用途与使用细节吧ui

组件实例周期

这一块vue2的官方文档有一张图示,咱们简要提一下用法和注意

beforeCreate

在实例初始化以后,数据观测(data observer) 和 event/watcher 事件配置以前被调用。

tip:

此时组件的选项还未挂载,所以没法访问methods,data,computed上的方法或数据

created

实例已经建立完成以后被调用。在这一步,实例已完成如下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

这是一个经常使用的生命周期,由于你能够调用methods中的方法、改变data中的数据,而且修改能够经过vue的响应式绑定体如今页面上、获取computed中的计算属性等等。

tip:

一般咱们能够在这里对实例进行预处理。
也有一些童鞋喜欢在这里发ajax请求,值得注意的是,这个周期中是没有什么方法来对实例化过程进行拦截的。
所以假若有某些数据必须获取才容许进入页面的话,并不适合在这个页面发请求。
建议在组件路由勾子beforeRouteEnter中来完成。

beforeMonut

在挂载开始以前被调用:相关的 render 函数首次被调用。

mounted

el 被新建立的 vm.$el 替换,并挂载到实例上去以后调用该钩子。若是 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。

tip:

1.在这个周期内,对data的改变能够生效。可是要进下一轮的dom更新,dom上的数据才会更新。
2.这个周期能够获取 dom。 以前的论断有误,感谢@冯银超 和 @AnHour的提醒
3.beforeRouteEnter的next的勾子比mounted触发还要靠后
4.指令的生效在mounted周期以前

beforeUpdate

数据更新时调用,发生在虚拟 DOM 从新渲染和打补丁以前。你能够在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。

updated

因为数据更改致使的虚拟 DOM 从新渲染和打补丁,在这以后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,因此你如今能够执行依赖于 DOM 的操做。然而在大多数状况下,你应该避免在此期间更改状态,由于这可能会致使更新无限循环。

beforeDestroy

实例销毁以前调用。在这一步,实例仍然彻底可用。

tip:

1.这一步还能够用this来获取实例。
2.通常在这一步作一些重置的操做。好比清除掉组件中的 定时器 和 监听的dom事件

destroyed

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

全局路由钩子

做用于全部路由切换,通常在main.js里面定义

router.beforeEach

示例
router.beforeEach((to, from, next) => {
  console.log('路由全局勾子:beforeEach -- 有next方法')
  next()
})

通常在这个勾子的回调中,对路由进行拦截。
好比,未登陆的用户,直接进入了须要登陆才可见的页面,那么能够用next(false)来拦截,使其跳回原页面。
值得注意的是,若是没有调用next方法,那么页面将卡在那。

next的四种用法
1.next() 跳入下一个页面
2.next('/path') 改变路由的跳转方向,使其跳到另外一个路由
3.next(false)  返回原来的页面
4.next((vm)=>{})  仅在beforeRouteEnter中可用,vm是组件实例。

router.afterEach

示例
router.afterEach((to, from) => {
  console.log('路由全局勾子:afterEach --- 没有next方法')
})

在全部路由跳转结束的时候调用,和beforeEach是相似的,可是它没有next方法

组件路由勾子

和全局勾子不一样的是,它仅仅做用于某个组件,通常在.vue文件中去定义。

beforeRouteEnter

示例
  beforeRouteEnter (to, from, next) {
    console.log(this)  //undefined,不能用this来获取vue实例
    console.log('组件路由勾子:beforeRouteEnter')
    next(vm => {
      console.log(vm)  //vm为vue的实例
      console.log('组件路由勾子beforeRouteEnter的next')
    })
  }

这个是一个很不一样的勾子。由于beforeRouterEnter在组件建立以前调用,因此它没法直接用this来访问组件实例。
为了弥补这一点,vue-router开发人员,给他的next方法加了特技,能够传一个回调,回调的第一个参数便是组件实例。
通常咱们能够利用这点,对实例上的数据进行修改,调用实例上的方法。

咱们能够在这个方法去请求数据,在数据获取到以后,再调用next就能保证你进页面的时候,数据已经获取到了。没错,这里next有阻塞的效果。你没调用的话,就会一直卡在那

tip:

next(vm=>{console.log('next')  })
这个里面的代码是很晚执行的,在组件mounted周期以后。没错,这是一个坑。你要注意。
beforeRouteEnter的代码时很早执行的,在组件beforeCreate以前;
可是next里面回调的执行,很晚,在mounted以后,能够说是目前我找到的,离dom渲染最近的一个周期。

beforeRouteLeave

beforeRouteLeave (to, from, next) {
    console.log(this)    //能够访问vue实例
    console.log('组件路由勾子:beforeRouteLeave')
    next()
  },

在离开路由时调用。能够用this来访问组件实例。可是next中不能传回调。

beforeRouteUpdate

这个方法是vue-router2.2版本加上的。由于原来的版本中,若是一个在两个子路由之间跳转,是不触发beforeRouteLeave的。这会致使某些重置操做,没地方触发。在以前,咱们都是用watch $route来hack的。可是经过这个勾子,咱们有了更好的方式。

老实讲,我没用过这个勾子,因此各位能够查看一下文章以前的文档,去尝试一下,再和我交流交流。

指令周期

绑定自定义指令的时候也会有对应的周期。
这几个周期,我比较经常使用的,通常是只有bind。

bind

只调用一次,指令第一次绑定到元素时调用,用这个钩子函数能够定义一个在绑定时执行一次的初始化动做。

inserted

被绑定元素插入父节点时调用(父节点存在便可调用,没必要存在于 document 中)。
其实是插入vnode的时候调用。

update

被绑定元素所在的模板更新时调用,而不论绑定值是否变化。经过比较更新先后的绑定值,能够忽略没必要要的模板更新。
慎用,若是在指令里绑定事件,而且用这个周期的,记得把事件注销

componentUpdated

被绑定元素所在模板完成一次更新周期时调用。

unbind

只调用一次, 指令与元素解绑时调用。

Vue.nextTick、vm.$nextTick

示例:
  created () {
    this.$nextTick(() => {
      console.log('nextTick')  //回调里的函数一直到真实的dom渲染结束后,才执行
    })
    console.log('组件:created')
  },

nextTick方法的回调会在dom更新后再执行,所以能够和一些dom操做搭配一块儿用,如 ref。
很是好用,能够解决不少疑难杂症。

场景:
你用ref得到一个输入框,用v-model绑定。
在某个方法里改变绑定的值,在这个方法里用ref去获取dom并取值,你会发现dom的值并无改变。
由于此时vue的方法,还没去触发dom的改变。
所以你能够把获取dom值的操做放在vm.$nextTick的回调里,就能够了。

vue生命周期探究(二)

相关文章
相关标签/搜索