Vue的生命周期

Vue的生命周期/钩子函数

在这里插入图片描述

什么是生命周期

Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载DOM、渲染---->更新---->渲染、卸载等一系列过程,称为Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。

所有的生命周期钩子函数自动绑定’this’到实例中, 因此可以根据this访问数据,对属性和方法进行运算,也就是说Vue的整个生命周期中提供的一系列事件中的this指向的就是Vue实例。同时意味着不能使用箭头函数来定义一个声明周期方法,因为箭头函数中的’this’,是跟父级有绑定的,所以箭头函数中的’this’与钩子函数中的this不同;
l例如:
正确方式:
created() { // 钩子函数只能用函数体方式定义 }
错误方式:
created => { // 用箭头函数的方式定义钩子函数是错误的, 此方式不可取; }

Vue中生命周期分为初始化、更新、销毁三个阶段;

  1. 初始化: beforeCreate、created、beforeMount、mounted;
  2. 更新: beforeUpdate、updated;
  3. 销毁: beforeDestory、destoryed;

其中created和mounted可以用来发送ajax请求, 启动定时器等异步任务;
beforeDestory用来做收尾工作,eg:清除定时器;

new Vue实例

此时只是初始化下Vue实例,初始化事件系统,初始化声明周期函数;

beforeCreate

调用时机: 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用(也就是说data、watcher、methods都还没有,但是$route对象是存在的);
详情: 根据组件中data中声明的数据, 把它们每一个数据都进行getter / setter劫持,赋值到this组件实例上(也就是说data上所有的数据都绑定到this上), 同时处理依赖data数据的watch、computed等数据;
完成的项: 触发beforeCreate时,仅仅是初始化的准备工作做好了, 完成了组件的实例化,事件、钩子函数声明都初始化好了;

created

调用时机: 在实例创建完成后被立即调用。
详情: 1. 在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算,watch / event事件回调。然而,挂载阶段还没开始,$el属性目前不可见。
2. 根据传入的配置项rende(函数)r>template>el(el即声明了模板也声明了挂载点, el指将来dom元素挂载到什么地方), 找到模板,准备解析,但是还没有开始挂载;
完成的项: 此时数据处理完成完成了组件的数据劫持,组件中的data、watch、computed通过路由传递的参数等数据都已经准备好了;
能做什么: 此时可以使用这些数据发起ajax请求;

new Vue({
  data: {
    a: 1
  },
  created: function () {
    // 'this'指向 vm 实例
    console.log('a is:' + this.a)
  }
})
// 打印结果: a is: 1

beforeMount

调用时机: 在挂载开始之前被调用: 相关的 render 函数首次被调用(此时模板还没有被解析出来);
详情: 该钩子在服务器渲染期间不被调用;
完成的项: 完成了模板的查找工作(但模板并没有解析只是找到了);
能做什么: 解析模板, 解析其中的指令, 替换其中的数据变量, 绑定事件, 渲染成一个浏览器认识的dom字符串,挂载到指定的节点上;

mounted

调用时机: el 被新创建的 vm.’&'el 替换, 并挂载到实例上去之后调用该钩子函数(vm是ViewModel的缩写,vm变量名表示Vue实例; Vue上自身的属性和方法都带有¥的英文符号,用于和开发者自己定义的属性与方法区分开);
详情:
完成的项: 已经完成了模板的解析(指令解析、事件绑定、数据的替换),生成了浏览器真正识别的dom字符串,并挂载到el声明的挂载点上;
能做什么: 可以获取模板中元素的dom节点; 执行了某个业务逻辑(增删改),更新数据;
注意:
mounted不会承诺所有的子组件也都一起被挂载。如果希望等到整个视图都渲染完毕,可以用vm.$nextTick替换掉mounted,如:

mounted: function () {
  this.$nextTick(function () {
    // **该钩子函数在服务器端渲染期间不被调用**;
  })
}

beforeUpdate

调用时机: 数据更新时调用,发生在虚拟DOM打补丁之前;
详情: 这里是个在更新之前访问现有的DOM,eg:手动移除已添加的事件监听器;
完成的项: 此时数据是新的;
能做什么: 使用新的数据更新视图;页面响应式数据发生变化后触发该钩子函数,此时数据已经是新的,页面的内容还是旧的。
注意: 该钩子函数在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行; 此时数据是新的,页面显示还是旧的数据;

updated

调用时机: 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后调用该钩子函数;
详情: 这个钩子函数被调用时,组件DOM已经更新,所以现在可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。如果要相应状态改变,通常最好使用计算属性watcher取而代之;
完成的项: 此时数据是新的,视图显示也是新的;
能做什么: 响应式数据更新后引起dom更新,dom更新后触发该钩子函数;
注意: 1.当我们离开这个页面时,页面中的组件都即将被销毁, 先触发beforeDestory: 执行以下清理(不使用的数据、定时任务等)工作;
2… updated不会承诺所有的子组件也都一起被重绘。如果希望等到整个视图都重绘完毕,可以用Vm.$nextTick替换掉updated, 如:

updated: function () {
  this.$nextTick(function () {
    **该钩子在服务器端渲染期间不被调用**
  })
}

activated

调用时机: 当使用 Keep-alive组件包裹的组件再次被显示使用时触发该钩子函数;
详情:
完成的项:
能做什么:
注意: 该钩子在服务器端渲染期间不被调用

deactivated

调用时机: 当使用keep-alive组件包裹的组件被隐藏时触发该钩子函数;
详情:
完成的项:
能做什么:
注意: 该钩子在服务器端渲染期间不被调用

beforeDestroy

调用时机: 实例销毁之前调用;
详情:
完成的项:
能做什么: 即将离开这个组件(非缓存组件)不再使用时,触发该钩子函数,在这里可以执行一些数据/定时器清理工作;
注意: 该钩子在服务器端渲染期间不被调用,在这一步实例仍然可用。

destroyed

调用时机: Vue实例销毁之后调用;
详情: 调用后, Vue实例指示的所有东西都会解绑定, 所有的事件监听器都会被移除,所有的子实例也会被销毁。
完成的项:
能做什么: 当组件销毁后触发该钩子函数,此时组件的响应式数据、侦听器、计算属性、绑定的事件都不再有效;
注意: 该钩子在服务器端渲染期间不被调用

代码验证

<body>
    <div id="test">
        <!-- 点击按钮后触发destoryVue事件 -->
        <button @click="destoryVue">destory vue</button>
        <p v-if="isShow">你好</p>
    </div>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript">
      new Vue ({
          el: '#test',
          data: {
              isShow: true
          },
          beforeCreate () {
              // 初始化Vue实例后触发;
              // 此时仅仅是初始化的准备工作做好了;
              console.log('beforeCreate()')
              console.log('beforeCreate 页面数据: ' this.data)
              console.log('beforeCreate 页面节点: ' this.$el)
          },
          created () {
              // 实例创建完成后被立即调用;
              // 此时可以发起ajax请求;
              console.log('created()')
          },
          beforeMount () {
              // 挂载开始之前被调用;
              // 开始解析模板;
              console.log('beforeMount()')
          },
          mounted () {
              // 挂载之后被调用;
              // 可以获取模板中元素的dom节点,已更新了数据;
              console.log('mounted()')
              // 执行异步任务
              this.intervalId = setInterval(() => {
                  console.log('------')
                  this.isShow = !this.isShow //isShow值为false时, P标签不显示 
              }, 1000)
          },
          beforeUpdate () {
              // 数据更新时调用, 在虚拟DOM打补丁之前;
              // 此时数据是新的,但页面显示的数据还是旧的;
              console.log('beforeUpdate()')
          },
          updated () {
              // 虚拟DOM重新渲染和打补丁之后被调用;
              // 此时数据和页面数据都是新的;
              console.log('updated()')
          },
          beforeDestroy () {
              // 实例销毁之前调用;
              // 此时实例仍然可用;
              console.log('beforeDestory()')
              // 执行收尾的工作
              clearInterval(this.intervalId)
          },
          destroyed () {
              // Vue实例销毁之后调用;
              console.log('destoryed()')
          },
          methods: {
              destoryVue () {
                  // 点击按钮后执行destroy()事件,开始销毁
                  this.$destroy() // 触发beforeDestory 和 destoryed的例子
              }
          }
      })
      /*
        执行结果: 
        beforeCreate()
        created()
        beforeMount()
        mounted()
        vue.js:8553 You are running Vue in development mode.
        Make sure to turn on production mode when deploying for production.
        See more tips at https://vuejs.org/guide/deployment.html
        ------
        beforeUpdate()
        updated()
        ------
        beforeUpdate()
        updated()
        ------
        beforeUpdate()
        updated()
        beforeDestory()
        destoryed()
      */
    </script>
</body>

父子组件的生命周期执行顺序

  1. 组件嵌套2层(父子组件<无第三层>):
  • 全流程:
    父组件beforeCreate --> 父组件created --> 父组件beforeMount --> 子组件beforeCreate --> 子组件created --> 子组件beforeMount --> 子组件mounted --> 父组件mounted --> 父组件beforeUpdate --> 子组件beforeUpdate --> 子组件updated --> 父组件updated --> 父组件beforeDestroy --> 子组件beforeDestroy --> 子组件destroy --> 父组件destroy

  • 加载渲染过程:
    父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

  • 子组件更新过程:
    父beforeUpdate->子beforeUpdate->子updated->父updated

  • 父组件更新过程:
    父beforeUpdate->父updated

  • 销毁过程:
    父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值