Vue生命周期

361 阅读3分钟

什么是生命周期?

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

简单来说,生命周期就是每个Vue实例创建、绑定数据、渲染数据、更新数据、销毁的过程

生命周期的作用

生命周期为我们提供了8个钩子函数,在渲染数据和控制vue实例的时候更方便也容易形成更好的逻辑

生命周期图示

  

总结执行的顺序就是:beforeCreate --> created --> beforeMount --> mounted --> beforeUpdate --> updated --> beforeDestroy -->destroyed

接下来,我们详细说说每个钩子。

beforeCreate 

  在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

这时候我们还不能访问实例中的方法和数据,看以下示例就知道了。

在组件Life中定义一个数据name,看在beforeCreate能不能访问的到

export default {
  name: "Life",
  data(){
    return {
      name: 'zs'
    }
  },
  beforeCreate() {
    console.log('beforeCreate-->',this.name);
  }
}

很明显在beforeCreate是访问不到的

created 

  在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el property 目前尚不可用。

这个时候我们就可以访问实例中的方法和数据了

具体我们看代码实现

export default {
  name: "Life",
  data(){
    return {
      name: 'zs'
    }
  },
  created() {
    console.log('created-->',this.name);
  }
}

beforeMount

在挂载开始之前被调用:相关的 render 函数首次被调用。

这个时候已经生成html模板,但是数据还没渲染上去  

我们怎么验证呢

我们在页面上定义一个p标签,并且把name作为内容

<p>{{name}}</p>

我们在beforeMount中获取这个p标签,并打印出来

beforeMount() {
  console.log(document.querySelector('p'));
}

查看下结果

mounted

实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。

页面已经完全加载好了,我们可以在这个生命周期中进行网络请求,但是我一般会在created中请求。

注意 mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick

我们在mounted中执行下beforeMount中的代码查看下结果

  

mounted() {
  console.log(document.querySelector('p'));
}

这个时候已经渲染到页面上了

beforeUpdate

数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

这时候数据已经更新了,但是页面上的数据还没更新  

我们通过定义一个按钮,改变data中的name,来观察下p标签中name有没有变化

<button @click="show">改变</button>
show(){
  this.name = 'ls'
}beforeUpdate() {
  console.log(this.name);
  console.log('beforeUpdate-->',document.querySelector('p').innerText);
}

看下结果

没点击之前

点击之后

对比之后我们发现,虽然数据已经发生改变,但是在beforeupdate中并没有发生变化

updated

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

数据修改已经完成,而且页面上的数据也已经更新完成  

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性watcher 取而代之。

在updated中执行beforeupdate中的代码,看下执行结果

beforeDestroy  

实例销毁之前调用。在这一步,实例仍然完全可用。

beforedestroy是我们最后能访问到组件数据和方法的函数

我们可以通过v-if来模拟销毁组件,在组件中打印下数据和元素

<Life v-if="isshow"></Life>
<button @click="show">删除组件</button>
show(){
  this.isshow = false
}

组件内代码:

beforeDestroy() {
  console.log(this.name);
  console.log('beforeDestroy-->',document.querySelector('p'));
},

当我们点击删除按钮时,打印结果

destroyed

实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。

我们同样在destroyed中执行beforedestroy相同代码

destroyed() {
  console.log('destroyed-->',document.querySelector('p'));}

这时候已经完全销毁了。

注意点:只有在组件被销毁的时候才会执行这个方法,不管这个方法可不可以访问到实例的数据和方法,都不要在这个生命周期中操作组件中的数据和方法