聊聊vue生命周期,并简单实现

469 阅读3分钟

前言

Vue实例有一个完整的生命周期,也就是从开始创建数据、编译模板、挂载DOM、渲染、更新、渲染、卸载等一系列过程,即一个组件从创建到销毁的过程,我们称这是Vue的生命周期。

Vue生命周期介绍

生命周期包括:创建前后(beforeCreate/created)、挂载前后(beforeMount/mounted)、更新前后(beforeUpdate/updated)、销毁前后(beforeDestory/destoryed)。注意单词的书写,前的是不用-d/-ed,后的需要-ed

接下来对每一个周期进行分析

  1. beforeCreate:创建前,此时datamethods都还未初始化,所以不能调用
  2. created:创建后,此时datamethods已经初始化,可以调用
  3. beforeMount:挂载前,此时template已经生成但未挂载到页面,页面和created一样
  4. mounted:挂在后,此时vue实例已经初始化完成,dom已经挂载到页面,可以操作dom和第三方dom
  5. beforeUpdate:更新前,此时data等已经更新,但是没有同步到页面
  6. updated:更新后,此时已经同步到页面中。
  7. beforeDestory:销毁前,此时vue实例进入销毁阶段,datamethods、指令、过滤器都还没被销毁,可以正常使用
  8. destoryed:销毁后,此时组件已经被销毁,不能调用datamethods

我们可以通过打印到控制台,来查看哪个阶段有哪些东西

Snipaste_2022-05-13_15-10-35.png

Snipaste_2022-05-13_15-11-14.png

所以就是:

  • beforeCreate啥都没有
  • createdel没有、data有了
  • beforeMountel没有、data有了(和created一样)
  • mountedel有、data

如果新增keep-alive,那么会新增两个生命周期

包裹动态组件的时候,会缓存不活动的组件实例,而不是摧毁他们

  • activated:页面激活的钩子函数,进入页面触发
  • deactivated:销毁时触发的钩子函数

我们需要知道如果第一次进入页面会执行:beforeCreatecreatedbeforeMountmountedactivated五个函数

如果是第二次或以上会执行:deactivated

Vue生命周期的实现

我将生命周期的实现分为三步:创建生命周期函数、创建el,data属性、按顺序执行执行el和data

第一步:

创建vue构造函数,通过new Vue()生成一个vue对象。再为vue设置生命周期函数,构造函数中按顺序执行。

index.html

  <script src="./vue.js"></script>
  <script>
    new Vue({
      beforeCreate() {
        console.log('beforeCreate')
      },
      created() {
        console.log('created')
      },
      beforeMount() {
        console.log('beforeMount')
      },
      mounted() {
        console.log('mounted')
      },
    })
  </script>

vue.js

class Vue {
  constructor(options) {
    options.beforeCreate()
    options.created()
    options.beforeMount()
    options.mounted()
  }
}

最简单的vue生命周期就完成了。此时,不管调用构造函数顺序如何改变,它们的执行顺序都是不会变的。

效果:

Snipaste_2022-05-13_16-04-59.png

第二步:

vue新增两个属性:eldata

增加完后,需要将this指向为Vue

index.html

<body>
  <div id="app"></div>
  <script src="./vue.js"></script>
  <script>
    new Vue({
      el: "#app",
      data: {
        name: '张三'
      },
      beforeCreate() {
        console.log('beforeCreate', this.$el, this.$data)
      },
      created() {
        console.log('created', this.$el, this.$data)
      },
      beforeMount() {
        console.log('beforeMount', this.$el, this.$data)
      },
      mounted() {
        console.log('mounted', this.$el, this.$data)
      },
    })
  </script>
</body>

vue.js

class Vue {
  constructor(options) {
  
    this.$data = options.data
    
    this.$el = document.querySelector(options.el)
    
    options.beforeCreate.call(this)
    
    options.created.call(this)
    
    options.beforeMount.call(this)
    
    options.mounted.call(this)
    
  }
}

到这里就完成了el和data属性的增加,但是el和data的挂载时机还没修改

效果:

Snipaste_2022-05-13_16-04-10.png

第三步:

最后,想要让不同生命周期执行不同的事情,只需要将el和data的顺序改变即可

vue.js

class Vue {
  constructor(options) {
  
    options.beforeCreate.call(this)
    
    this.$data = options.data
    
    options.created.call(this)
    
    options.beforeMount.call(this)
    
    this.$el = document.querySelector(options.el)
    
    options.mounted.call(this)
    
  }
}

效果:

Snipaste_2022-05-13_16-10-02.png

到这里,一个简单的vue生命周期就做好了

总结

  • 生命周期一共有八个,第一次进入页面执行顺序是:beforeCreatecreatedbeforeMountmounted
  • 如果新增标签,那么就会多两个(activateddeactivated),第一次进入页面执行顺序:beforeCreatecreatedbeforeMountmountedactivated