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
    评论
Vue生命周期钩子函数指的是在组件实例化、渲染、更新和销毁等不同阶段执行的一些特定函数。下面是 Vue 组件生命周期钩子函数及其执行顺序: 1. beforeCreate:在实例创建之前被调用。此时组件的数据和方法都还未初始化。 2. created:在实例创建完成之后被调用。此时组件的数据已经初始化,但 DOM 还未渲染。 3. beforeMount:在组件挂载到 DOM 之前被调用。此时模板已经编译完成,但还未挂载到页面中。 4. mounted:在组件挂载到 DOM 后被调用。此时组件已经被渲染并插入到页面中,可以进行 DOM 操作。 5. beforeUpdate:在数据更新之前被调用。此时组件还未重新渲染,但数据已经更新。 6. updated:在数据更新之后被调用。此时组件已经重新渲染,可以进行 DOM 操作。 7. beforeDestroy:在组件销毁之前被调用。此时组件还存在,可以进行一些清理工作。 8. destroyed:在组件销毁之后被调用。此时组件已经从 DOM 中移除,事件监听和定时器等资源都已经被销毁。 对于父子组件,它们的生命周期钩子函数的执行顺序如下: 1. 父组件的 beforeCreate 和 created 钩子函数执行。 2. 子组件的 beforeCreate 和 created 钩子函数执行。 3. 子组件的 beforeMount 钩子函数执行。 4. 子组件的 mounted 钩子函数执行。 5. 父组件的 beforeMount 钩子函数执行。 6. 父组件的 mounted 钩子函数执行。 7. 数据更新时,先执行父组件的 beforeUpdate 钩子函数,然后执行子组件的 beforeUpdate 钩子函数,再执行子组件的 updated 钩子函数,最后执行父组件的 updated 钩子函数。 8. 组件销毁时,先执行父组件的 beforeDestroy 钩子函数,然后执行子组件的 beforeDestroy 钩子函数,最后执行子组件的 destroyed 钩子函数,再执行父组件的 destroyed 钩子函数。 这是 Vue 组件生命周期钩子函数的一般执行顺序,但在实际开发中可能会有特殊情况,需要根据具体需求来使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值