【Vue.js】生命周期与钩子函数

1、生命周期

Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、设置数据监听、编译模板、将实例挂载到 Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗地说就是Vue实例从创建到销毁的过程,就是生命周期。同时在这个过程中状态不同也会运行一些叫做生命周期钩子的函数,这也给了我们在不同阶段添加代码的机会。

结合vue的早期版本发现2.0版本下的生命周期变得更加语义化,让初始化、执行、销毁等各个阶段状态更加清晰,而且增加了beforeUpdate、updated、activated、deactivated,删除了attached、detached钩子函数。

vue早期版本vue2.0描述
initbeforeCreate实例刚被创建 组件属性计算之前被调用
createdcreated在实例创建完成时调用 所有指令都被绑定,所有的事件监听器都已完成,挂载阶段还没开始,$el 属性目前尚不可用。
beforeCompilebeforeMount模板编译、挂载之后调用;相关的 render 函数首次被调用
compilemounted模板编译、挂载之后调用
readymounted实例被挂载后调用,el 被新创建的 vm.$el 替换
-beforeUpdate数据更新时调用 ,该钩子在服务端渲染期间不被调用,因为只有初次渲染会在服务端进行。
-updated数据更改导致的虚拟 Dom 重新渲染完成后调用 。该钩子在服务端渲染期间不被调用
-activated被 keep-alive 缓存的组件激活时调用。该钩子在服务端渲染期间不被调用。
-deactivated被 keep-alive 缓存的组件停用时调用。该钩子在服务端渲染期间不被调用。
-errorCaptured当捕获一个来自子孙组件的错误时被调用。
attached-由指令或实例方法将$el 插入 Dom 时被调用,直接操作 $el不触发
detached-由指令或实例方法将$el从Dom中删除时被调用,直接操作 $el不触发
beforeDestorybeforeDestory实例销毁之前调用。此时实例仍然完全可用。该钩子在服务器端渲染期间不被调用。
destoryeddestoryed实例销毁后调用。对应实例的所有指令、事件、子实例都被销毁。

2、钩子函数

每一个组件或者实例都会经历一个完整的生命周期,下面我们结合代码详细地来聊一聊生命周期的各个历程。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>vue.js-2.16.11</title>
  <script src="../../vue.js"></script>
</head>

<body>
  <div id="app">
    {{city}}
  </div>
  <script>
    var vm = new Vue({
      el: "#app",
      data: {
        city: 'beijing',
        company:"jd",
        date:"2020",
        versions:"2.16.11"
      },
      beforeCreate() {
        console.log("beforeCreate(在实例创建以前):this.city==========>", this.city)
        console.log("this.$el:======================Dom=============>",this.$el)
        this.city = "nanjing";
      },
      created() {
     
        console.log('created(实例创建完成):========this.city=========>', this.city)
        console.log("this.$el:======================Dom=============>",this.$el)
        this.city = "shanghai";

      },
      beforeMount() {
        console.log('beforeMount(在挂载之前):======this.city=========>',this.city)
        console.log("this.$el:======================Dom=============>",this.$el)
        console.log("document.getElementById==========>",document.getElementById("app"))
        this.city = "shengzhen";
      },
      mounted() {
        console.log('mounted(已经挂载):============this.city=========>',this.city);
        console.log("this.$el:======================Dom=============>",this.$el)
        this.city = "nanjing";
        setTimeout(() => {
          vm.$destroy();
          console.log("实例卸载")
        }, 3000)
      },
      beforeUpdate() {
        console.log('beforeUPdate(更新之前):====this.city============>',this.city)
      },
      updated() {
        console.log('updated(更新之后):=========this.city============>',this.city)
      },
      beforeDestroy() {
        console.log('beforeDestroy(实例销毁前):=this.city============>',this.city)
      },
      destroyed() {
        console.log('destroyed(实例销毁后):====this.city=============>',this.city)
      }
    })
  </script>
</body>
</html>

::::::::::::::::::::::::::::在这里插入图片描述
结合控制台打印结果我们可以发现:
1.beforeCreate( ):在这个钩子函数中data与Dom都显示undefined;这是因为虽然此时通过new Vue() 创建出来的实例会初始化事件和生命周期,但数据观测 (data observer) 和 event/watcher 事件配置还没有完成,因此无法访问到数据和真实的Dom。

2.created( ):在这个钩子函数中能访问和修改data下的数据;但是不能获取不到最终渲染后Dom,修改数据不会触发updated ,beforeUpdate 函数;这是因为在实例创建完成后所有指令都被绑定,实例属性已经计算完成,所有的事件监听器都已设置完毕,但挂载阶段还没开始,所以$el 属性目前尚不可用;实例创建的初次渲染会在服务端进行;而updated ,beforeUpdate 函数底层设置了该钩子在服务端渲染期间不被调用,因而不会触发函数。一般在这里可以做初始数据的获取,也可以实现最早发送ajax数据请求。

3.beforeMount( ):接下来开始找实例对应的模板,将模板编译为虚拟Dom放入到render函数中准备渲染,然后执行beforeMount钩子函数,此时在虚拟Dom已经创建完成;所以挂载在之前,$el和data都已经初始化了,在这里可以在渲染前最后一次更改数据的机会;一般可以在这里做初始数据的获取;同样这里更改数据也不会触发其他的钩子函数。

4.mounted( ):接着执行框架底层render函数渲染出真实的Dom;此时Vue实例已经挂载完成了;真实的Dom节点也已经渲染到页面,这是创建实例以来首次可以操作渲染后的Dom。因此此时再次当组件或实例的数据更改之后,就会立即执行beforeUpdate,updated钩子函数,重新更新数据、渲染Dom。

5.beforeUpdate( ). 当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟Dom机制会重新构建虚拟Dom与上一次的虚拟Dom树利用diff算法进行对比之后重新渲染。

6.updated( ). 当更新完成后,执行updated,数据已经更改完成,Dom也重新执行渲染完成,就可以操作更新后的虚拟Dom。

7.beforeDestroy( ). 当经过某种途径调用$destroy方法后,就会立即执行beforeDestroy,而beforeDestroy 钩子函数的执行时机是在 $destroy 函数执行最开始的地方,接着执行了一系列的销毁动作,包括从 parent 的 $children 中删掉自身,删除 watcher,当前渲染的 VNode 执行销毁钩子函数等.,data里的数据没有变化,但是Dom结构还存在,也就是Vue实例不再受控制了,完成了解耦。一般在这里做一些善后工作例如"你确认删除吗?"提示框,还可以进行清除计时器、清除非指令绑定的事件等等操作,防止内存泄漏。执行完毕后再调用 destroyed钩子函数.

8.destroyed( ). 在destroyed钩子函数的执行过程中它又会执行 vm.patch(vm._vnode, null) 触发它子组件的销毁钩子函数,这样一层层的递归调用,所以 destroyed钩子函数执行顺序是先子后父,此时已经解除实例的数据绑定、侦听,页面只剩下Dom结构的空壳。也可以在这里做些善后工作,例如:当前组件已被删除,清空相关内容等等。
在这里插入图片描述
生命周期图示
本图来源于vue.js官方文档2.0版本中给出实例的生命周期。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值