Vue生命周期的理解

229 阅读2分钟

image

测试代码:

    <div id="app">
        <h2>{{ msg }}</h2>
        <button @click="init" type="button">点击</button>
    </div>
    <script>
     var vm =  new Vue({
        el: '#app',
        data: {
          msg: "hello word!"
        },
        methods: {
          init () {
            alert('init');
          }

        },
        beforeCreate () {
          console.log('======beforeCreate=====');
          console.log(`el: ${this.$el}`);
          console.log(`data: ${this.$data}`);
          console.log(`init: ${this.init}`);
        },
        created () {
          console.log('======created=====');
          console.log(`el: ${this.$el}`);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
          // this.$data.msg = '1111'; // 这是可以对数据进行更改,但是不会触发update生名周期函数,所以一般会在这里做数据请求
        },
        beforeMount (){
          console.log('======beforeMount=====');
          console.log(`el: ${this.$el}`);
          console.log(this.$el);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
          // 这里不做任何事,同时也不能修改数据
        },
        mounted () {
          console.log('======mounted=====');
          console.log(`el: ${this.$el}`);
          console.log(this.$el);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
        },
        beforeUpdate () {
          console.log('======beforeUpdateupdated=====');
          console.log(`el: ${this.$el.innerHTML}}`);
          console.log(this.$el);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
        },
        updated () {
          console.log('======updated=====');
          console.log(`el: ${this.$el.innerHTML}`);
          console.log(this.$el);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
        },
        beforeDestroy () {
          console.log('======beforeDestroy=====');
          console.log(`el: ${this.$el}`);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
        },
        destroyed () {
          console.log('======destroyed=====');
          console.log(`el: ${this.$el}`);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
        }
      })
      // vm.$mount(app);
    </script>

  • beforCreate 和 created之间

    • 检测data数据的变化,初始化事件。
    • 这时候并没有el
  • created

    • 没有el, Dom 没有生成
  • created 和 beforMount之间

    • 首先判断是否有el选项,如果没有暂时停止生命周期,直到手动执行vm.mount(el),有则继续编译过程,继续执行
    • 在判断是否有template选项,如果没有采用外部html模版,否则采用template选项编译成render函数
    • 这里的render 指的是jsx写法。
    • 优先级 render > template > 外部的html
    • 在created时,是可以修改数据的,通常我们会在这里向服务器请求数据
  • ==问题==:为什么需要去判断el 和 template 选项呢?

  • ==结论==:首先我们需要el选择器,否则生命周期会暂时被终止,到created就停止了,所以el选择器为前提条件,必须在template之前,通过对应的el选择器拿到相对应的template。对于template优先级的问题,template编辑后都要转换成render函数,更接近Vue解析器,接着就是vue实例中的template选项了,如果template和外部的html同时存在,那么template优先级高于外部的html

  • beforMount

    • el、 data初始化,拿到了虚拟dom (virtual dom)这时的数据还未进行渲染,{{message}} 只是一个占位符。
  • Mounted

    • 渲染真实的Dom(适合操作dom)
  • beforeUpdate

    • 此时,元素的真实dom内容还未改变
  • Updated

    • 重新渲染虚拟 dom,并通过 diff 算法对比 vnode 节点差异更新真实 dom
  • beforeDestroy

  • destroyed

    • 实例销毁后虽然 dom 和属性方法都还存在,但改变他们都将不再生效!