Vue生命周期&父子组件的生命周期

Vue生命周期分析

 Vue实例完整的生命周期:从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁的过程。

生命周期钩子可分为三个部分:

  1. 组件挂载:beforeCreate, created, beforeMount, mounted
  2. 组件更新:beforeUpdate, updated
  3. 组件卸载:beforeDestroy, destroyed

beforeCreate

实例创建后,生命周期的初始化后被调用。

因为此时还没有完成事件初始化和数据观测,所以无法访问实例中的$el, data,method等,但是可以访问this对象。

在这个阶段可以为实例添加监测数据(例如:this.action = '为实例添加监测属性')

beforeCreate --> created

初始化事件,数据观测。

created

 Vue实例创建完后被调用。

此时已经完成了数据观测,属性和方法的运算,watch/event 事件回调的配置。

访问和修改data中的数据,会触发响应式变化使DOM渲染更新,触发watch中相应的方法,computed相关属性进行重新计算。

一般情况会进行ajax请求初始化实例数据,但是有缺陷(无法进行请求拦截,假如有某些数据必须获取允许进入页面的话,并不适合在这个方法发请求,建议在组件路由钩子beforeRouteEnter中完成)。

created -- beforeMount

// 这个创建实例指定#app为挂载的DOM节点
new Vue({
  el: '#app',
  render: h => h(App),
})

// 这个创建实例没有指定$el,在调用$mount()的时候进行指定挂载的DOM节点
new Vue({
  render: h => h(App),
}).$mount('#app')
 
  • 判断实例中是否有el选项(子组件的el为组件根元素),有的话继续向下编译,没有的话会停止编译,直到显式的调用vm.$mount(el)。
  • 判断实例中是否有template,有template将其作为模板编译成render函数;没有template就提取el的outerHTML出来作为模板编译;如果实例对象中有render函数,就直接通过它进行渲染操作。
  • 注意:el所对应的DOM元素不能为body/html元素,因为在后面vue实例挂载时,el所对应的DOM元素及其内部的元素会被模板渲染出来的新的DOM所替换。优先级:render函数 > template > outerHTML

beforeMount

挂载之前被调用,$el可见。

beforeMount -- mounted 

 在这个过程中生成虚拟DOM树,el被新创建的vm.$el所替换,并完成实例的挂载。即实例中的el选项被模板渲染创建出来的DOM元素所替换,页面中的挂载点被渲染出的vue实例代码段所替换

mounted

此时实例已挂载到DOM上,可以获取实例中DOM节点。在控制台打印vm.$el,发现之前的挂载点及内容已被替换成新的DOM。

如何使用了keep-alive,mounted 之后将触发activated钩子

beforeUpdate 和 updated

当data对象中数据更新时,会触发 beforeUpdate钩子,此时view层还没有更新。 beforeUpdate有下面几个需要注意的地方:

a、更新的数据必须在模板中直接或间接的使用,才会触发beforeUpdate;

b、在挂载之前data中数据更新不会触发 beforeUpdate;

c、如果在beforeUpdate中,再次修改了该数据的值,会再次触发beforeUpdate钩子,进行两次更新流程。

updated: view层已更新完毕。

beforeDestroy 和 destroyed

如何使用了keep-alive,会先触发deactivated钩子,然后在触发beforeDestroy和destroyed

 beforeDestroy:实例在销毁之前调用,此时实例仍然可用.

beforeDestroy -> destroyed: Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

destroyed:vue实例销毁后调用。

父子组件的生命周期

// 父组件
<template>
  <div class="about">
    <p @click="clickHandler">{{ name }}</p>
    <keep-alive>
      <hello-world :message="name"></hello-world>
    </keep-alive>
  </div>
</template>
<script>
import HelloWorld from '../components/HelloWorld'
export default {
  data(){
    return {
      name: "parent"
    }
  },
  components: {
    HelloWorld
  },
  methods: {
    clickHandler() {
      this.name = 'parent to child'
    }
  },
  beforeCreate() {
    console.group('parent_beforeCreate');
    console.log('this.$el:', this.$el);
    console.log('data:', this.name);
  },
  created() {
    console.group('parent_created');
    console.log('this.$el:', this.$el);
    console.log('data:', this.name);
  },
  beforeMount: function() {
    console.group('parent_beforeMount');
    console.log('this.$el:', this.$el);
    console.log('data:', this.name);
  },
  mounted: function() {
    console.group('parent_mounted');
    console.log('this.$el:', this.$el);
    console.log('data:', this.name);
  },
  beforeUpdate: function () {
    console.group("parent_beforeUpdate"); 
    console.log('更新前');
  },
  updated: function () {
    console.group("parent_updated");
    console.log('更新完');
  },
  beforeDestroy: function () {
      console.group('parent_beforeDestroy 销毁前状态');
      console.log('this.$el:', this.$el);
      console.log('data:', this.name);
  },
  destroyed: function () {
      console.group('parent_destroyed 销毁完成状态');
      console.log('this.$el:', this.$el);
      console.log('data:', this.name);
  }
}
</script>  



// 子组件
<template>
  <div class="hello">
    <h1>{{ message }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    message: String
  },
  data() {
    return {
      name: 'child'
    }
  },
  beforeCreate: function () {
    console.group('child_beforeCreate');
    console.log('this.$el:', this.$el);
    // console.log('props:',this.message);
    console.log('data:', this.name);
  },
  created: function () {
    console.group('child_created');
    console.log('this.$el:', this.$el);
    console.log('props:',this.message);
    console.log('data:', this.name);
  },
  beforeMount: function () {
    console.group('child_beforeMount');
    console.log('this.$el:', this.$el);
    console.log('props:',this.message);
    console.log('data:', this.name);
  },
  mounted: function () {
    console.group('child_mounted');
    console.log('this.$el:', this.$el);
    console.log('props:',this.message);
    console.log('data:', this.name);
  },
  activated: function () {
    console.group('child_activated');
    console.log('组件激活');
  },
  beforeUpdate: function () {
    console.group("child_beforeUpdate"); 
    console.log('更新前');
  },
  updated: function () {
    console.group("child_updated");
    console.log('更新完');
  },
  deactivated: function(){
    console.group('child_deactivated');
    console.log("组件失活");
  },
  beforeDestroy: function () {
    console.group('child_beforeDestroy');
    console.log('this.$el:', this.$el);
    console.log('props:',this.message);
    console.log('data:', this.name);
  },
  destroyed: function () {
    console.group('child_destroyed');
    console.log('this.$el:', this.$el);
    console.log('props:',this.message);
    console.log('data:', this.name);
  }
}
</script>



创建过程

父子组件创建

更新过程

销毁过程

父子组件销毁

相关文章

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值