vue 之深入浅出各生命周期函数

vue 之深入浅出各生命周期函数

  • 一、vue 生命周期函数
  • 二、父子孙组件间各生命周期函数
  • 三、prop属性的传值三大问
  • 四、 mixin自定义选项合并策略

一、vue 生命周期函数

vue实例的创建都需要经历过一系列生命周期钩子函数,比如实例初始化、数据监听、数据渲染、实例挂载、数据更新等等。
周期函数执行案例:

<template>
  <div class="test-demo">
    <button @click="clickMethod">show</button>
    <button @click="updateMethod">update props</button>
    <father v-if="visible" :updateObj='updateObj'></father>
  </div>
</template>
<script>
import ViewMixin from '@/mixins/view-mixins.js'
import father from './components/father'
export default {
  name: 'TestDemo',
  mixins: [
    ViewMixin()
  ],
  components: {
    father
  },
  data() {
    return {
      visible: true,
      updateObj: {test: 1}
    };
  },
  methods: {
    clickMethod() {
      this.visible = !this.visible
    },
    updateMethod() {
      this.updateObj.test = ++this.updateObj.test
    }
  },
  beforeCreate: function() { // 创建实例前
    console.log('beforeCreate 钩子执行...:')
  },
  cteated: function() { // 创建实例时
    console.log('cteated 钩子执行...:')
  },
  beforeMount: function() { // 数据渲染前
    console.log('beforeMount 钩子执行...:')
  },
  mounted: function() { // 数据渲染时
    console.log('mounted 钩子执行...:')
  },
  beforeUpdate: function() { // 数据更新前
    console.log('beforeUpdate 钩子执行...:')
  },
  updated: function() { // 数据更新时
    console.log('updated 钩子执行...:')
  },
  beforeDestroy: function() { // 实例销毁前
    console.log('beforeDestroy 钩子执行...:')
  },
  destroyed: function() { // 实例销毁时
    console.log('destroyed 钩子执行...:')
  }
}
</script>

每个生命周期函数执行顺序如图:
vue 之深入浅出各生命周期函数_第1张图片

二、父子孙组件间各生命周期函数

每个组件都会有上述的生命周期函数,但父子类组件加载的顺序如何呢?通常在实际开发中会遇到全局变量在访问时没有实时同步例如vuex、或者接口请求不是按我们开发的顺序请求等等,这时可能与在组件内部钩子函数执行顺序有关。
案例如下,
父类组件:

<template>
 <div class="father">
   father
   <span>
     {{updateObj.test}}
   </span>
   <child :updateObj="updateObj"></child>
 </div>
</template>
<script>
import ViewMixin from '@/mixins/view-mixins.js'
import child from './child.vue'
export default {
 name: 'father',
 mixins: [
   ViewMixin()
 ],
 props: {
   updateObj: {
     type: Object
   }
 },
 components: {
   child
 },
 beforeCreate() {
   console.log('father-beforeCreate')
 },
 created() {
   console.log('father-created')
 },
 beforeMount() {
   console.log('father-beforeMount')
 },
 mounted() {
   console.log('father-mounted')
 },
 beforeUpdate() {
   console.log('father-beforeUpdate')
 },
 updated() {
   console.log('father-updated')
 },
 beforeDestroy() {
   console.log('father-beforeDestroy')
 },
 destroyed() {
   console.log('father-destroyed')
 }
}
</script>

子类组件:

<template>
 <div class="child">
   child
   <span>
     {{updateObj.test}}
   </span>
   <grandson :updateObj="updateObj"></grandson>
 </div>
</template>
<script>
import ViewMixin from '@/mixins/view-mixins.js'
import grandson from './grandson.vue'
export default {
 name: 'child',
 mixins: [
   ViewMixin()
 ],
 props: {
   updateObj: {
     type: Object
   }
 },
 components: {
   grandson
 },
 beforeCreate() {
   console.log('child-beforeCreate')
 },
 created() {
   console.log('child-created')
 },
 beforeMount() {
   console.log('child-beforeMount')
 },
 mounted() {
   console.log('child-mounted')
 },
 beforeUpdate() {
   console.log('child-beforeUpdate')
 },
 updated() {
   console.log('child-updated')
 },
 beforeDestroy() {
   console.log('child-beforeDestroy')
 },
 destroyed() {
   console.log('child-destroyed')
 }
}
</script>

孙类组件:

<template>
 <div class="grandson">
   grandson
   <span>
     {{updateObj.test}}
   </span>
 </div>
</template>
<script>
import ViewMixin from '@/mixins/view-mixins.js'
export default {
 name: 'grandson',
 mixins: [
   ViewMixin()
 ],
 props: {
   updateObj: {
     type: Object
   }
 },
 beforeCreate() {
   console.log('grandson-beforeCreate')
 },
 created() {
   console.log('grandson-created')
 },
 beforeMount() {
   console.log('grandson-beforeMount')
 },
 mounted() {
   console.log('grandson-mounted')
 },
 beforeUpdate() {
   console.log('grandson-beforeUpdate')
 },
 updated() {
   console.log('grandson-updated')
 },
 beforeDestroy() {
   console.log('grandson-beforeDestroy')
 },
 destroyed() {
   console.log('grandson-destroyed')
 }
}
</script>

组件的加载结果如下:
vue 之深入浅出各生命周期函数_第2张图片
组件销毁时结果如下:vue 之深入浅出各生命周期函数_第3张图片
组件更新时结果如下:
vue 之深入浅出各生命周期函数_第4张图片
总结:组件加载时各生命周期在mounted钩子之前按父类到子类的顺序逐步更新,父类组件实例节点加载完按从子到父的顺序执行mounted渲染;销毁时也按从子到父顺序执行destroyed,之前的钩子按父到子;组件更新时按子到父类执行updated,之前的钩子按父到子。

三、prop属性的传值三大问

  1. 问题1属性有默认值时,不给属性传值,属性的值会比data初始化绑定的值要早吗?
  2. 问题2 属性传值有默认值,也给属性赋予不同的值(能监听到属性的变化),组件加载之前(init)赋值和加载完成(mounted)时赋值,watch可以监听到变化吗?赋值组件在哪些生命周期函数里可以访问这个变化后的值呢?
  3. 问题3属性 传值(对象或者数组,亦或跟复杂嵌套的对象数组)有监听不到属性变化的情况吗?有时怎么处理,没有时为什么呢?。。

四、 mixin自定义选项合并策略

  1. 问题1相同方法混入时,合并后的方法是覆盖还是合并执行组件里相同的方法
  2. 问题2 相同属性、data、computed混入时,合并后访问属性、data、computed是混入里的还是组件里的。
  3. 合并策略是否可更改

后续持续更新。。。

你可能感兴趣的:(vue)