vue源码-生命周期

144 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

前言

学习框架,仅仅会使用是不够的,想要更熟悉框架,需要对源码有一定的了解。本篇文章通过vue源码解析,实现vue的生命周期。

介绍

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

实现

我认为,生命周期在vue源码中是比较容易实现的部分。生命周期其实就是函数的执行,只需要将每个生命周期的顺序排好就行。

上面讲了,vue生命周期一共有八个,初始化页面会执行四个,分别为:beforeCreatecreatedbeforeMountmounted

我们执行vue,来观察一下,初始化页面,四个钩子函数的执行顺序如何:

      beforeCreate() {
        console.log('beforeCreate');
      },
      created() {
        console.log('created');
      },
      beforeMount() {
        console.log('beforeMount');
      },
      mounted() {
        console.log('mounted');
      }

image-20220604164703414

执行结果可以看出,vue生命周期钩子是按照顺序执行的,如果我们打乱顺序,在观察一下生命周期钩子的执行属性呢

      beforeMount() {
        console.log('beforeMount');
      },
      created() {
        console.log('created');
      },
      beforeCreate() {
        console.log('beforeCreate');
      },
      mounted() {
        console.log('mounted');
      }

image-20220604164925987

可以看出,执行顺序依然不变。

所以,在vue生命周期中,不管你生命周期函数写的顺序如何,它执行顺序都是:beforeCreatecreatedbeforeMountmounted,那么这是如何实现的?

其实,就是在vue源码中,写好生命周期的执行顺序了,就算你调用时顺序乱了,但是执行顺序是写好了的。

接下来,我来实现一下vue生命周期,并分析什么时候有 data,什么时候有 el

  • 实现生命周期执行顺序

    • 判断传入的是否为函数

    • 判断是那一个钩子函数

        constructor(options) {
          if (typeof options.beforeCreate == 'function') {
            options.beforeCreate()
          }
          if (typeof options.created == 'function') {
            options.created()
          }
          if (typeof options.beforeMount == 'function') {
            options.beforeMount()
          }
          if (typeof options.mounted == 'function') {
            options.mounted()
          }
        }
      

      这样,vue生命周期执行顺序的问题就完成了

  • 实现生命周期 $data $el

    • 修改this指向。

      此时钩子函数中的this指向的是当前对象,是获取不到任何值的。$data$elvue构造函数里,应该要让他指向vue.js中的构造函数,通过.call(this),改变this指向

        constructor(options) {
          this.$el = document.querySelector(options.el)
          this.$data = options.data
          this.Parser(this.$el)
          if (typeof options.beforeCreate == 'function') {
            options.beforeCreate.call(this)
          }
          if (typeof options.created == 'function') {
            options.created.call(this)
          }
          if (typeof options.beforeMount == 'function') {
            options.beforeMount.call(this)
          }
          if (typeof options.mounted == 'function') {
            options.mounted.call(this)
          }
        }
      

      image-20220604171136410

    • 调整$data$el的输出时机

      此时,生命周期钩子中都可以获取到$datael,但我们希望能和vue生命周期一样,在beforeCreate中获取不到el,但我们希望能和`vue`生命周期一样,在`beforeCreate`中获取不到`datael,在createdbeforeMount可以获取到el`,在`created`和`beforeMount`可以获取到`data,在mounted中可以获取到datadata`和`el。只需要调整datadata`和`el`的获取位置即可

        constructor(options) {
          if (typeof options.beforeCreate == 'function') {
            options.beforeCreate.call(this)
          }
          this.$data = options.data
          if (typeof options.created == 'function') {
            options.created.call(this)
          }
          if (typeof options.beforeMount == 'function') {
            options.beforeMount.call(this)
          }
          this.$el = document.querySelector(options.el)
          if (typeof options.mounted == 'function') {
            options.mounted.call(this)
          }
          this.Parser(this.$el)
        }
      

      image-20220604171338168

总结

vue生命周期实现原理不难,就两点:按顺序执行钩子函数,在合适的事件获取数据和节点