[vue2] Vue's life cycle and data monitoring analysis

Version: vue2.X, ant design vue 1.7.8

1. What is the life cycle of vue?

Answer: The life cycle of vue is the process of a component being unloaded after initialization, mounting, updating and other steps from the creation;

It is equivalent to a jigsaw puzzle game in real life.
First, prepare the puzzle board and scattered puzzles in the initialization stage;
assemble the puzzle pieces one by one into the target pattern
in the mounting stage ; Buckle out the picture or put the new diy picture where it needs to be placed; the
unloading stage is equivalent to the process of dismantling and putting together the assembled puzzle after enjoying it


2. The life cycle hook functions are:

Mounting phase :
beforeCreate //Before creation of data detection and data proxy
created //Creation of data detection and data proxy is created
beforeMount //Before
mounting mounted //Mounting is complete
 
Update phase :
beforeUpdate //Update before update
//
 
Uninstallation (destruction) stage after updating :
beforeDestroy //before uninstalling
destroyed //unloading complete
 
cache (KeepAlive) stage :
activated //enter the page of the component deactivated // error prompt
when deactivating or leaving (but the component is not destroyed)
 
Phase :
errorCaptured //When capturing errors from descendant components
errorHandler //The specified component did not capture the error handling function during rendering and observation

2.1 Computed properties

computed //computed attribute
watch //data monitoring


3. Life cycle execution order


insert image description here
Practice on the page according to the example diagram in the official document , the code is as follows
home parent page

<template>
  <div style="padding: 60px">
    <h3 style="color: red">父页面</h3>
    <a-input v-model="message" style="width: 120px"></a-input>
    <div>{
    
    {
    
     message }}</div>
    <a-input v-model="test" style="width: 220px"></a-input>
    <a-input v-model="testList" style="width: 220px"></a-input>
    <h3 style="color: red">csdn博主:{
    
    {
    
     csdnName }}</h3>

    <a-button @click="showTap">点击卸载</a-button>
    <div>-----------------------------------------</div>
    <div v-if="isHomePageShow">
      <keep-alive>
        <homePage></homePage>
      </keep-alive>
    </div>
    <a-button @click="homePageShowTap">点击隐藏/显示子组件</a-button>
  </div>
</template>

<script>
import homePage from './components/homePage.vue'
export default {
    
    
  name: 'Home',
  components: {
    
    
    homePage,
  },
  data() {
    
    
    return {
    
    
      isHomePageShow: true,
      message: 'test',
      isImmediate: '是否开启watch数据监听默认调用',
      test: '监听数据变动调用一个封装方法',
      testList: '监听数据变动调用多个封装方法',
    }
  },
  computed: {
    
    
    csdnName() {
    
    
      console.group('------computed计算属性状态------')
      const name = '鱼干~'
      console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
      console.log('%c%s', 'color:red', 'data   : ' + this.$data) //undefined
      console.log('%c%s', 'color:red', 'csdn博主: ' + name)
      return name
    },
  },
  watch: {
    
    
    message: {
    
    
      handler(newVal, oldVal) {
    
    
        console.group('------watch数据监听状态------')
        console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
        console.log('%c%s', 'color:red', 'data   : ' + this.$data) //undefined
        console.log('%c%s', 'color:red', '新值: ' + newVal, '旧值: ' + oldVal)
      },
    },
    isImmediate: {
    
    
      handler(newVal, oldVal) {
    
    
        console.group('------watch数据监听在侦听开始之后立即调用、并且无论其被嵌套多深都可侦听状态------')
        console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
        console.log('%c%s', 'color:red', 'data   : ' + this.$data) //undefined
        console.log('%c%s', 'color:red', '新值: ' + newVal, '旧值: ' + oldVal)
      },
      immediate: true, //该回调将会在侦听开始之后立即调用,默认是false
      deep: true, //该回调将会在被侦听的对象的属性改变时调动,无论其被嵌套多深
    },
    // 字符串方法名称
    test: 'someMethod',
    //监听数据变动调用多个封装方法
    testList: [
      'testListSomeMethod',
      function handler2(newVal, oldVal) {
    
    
        console.group('------watch数据监听调用多个封装方法状态------')
        console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
        console.log('%c%s', 'color:red', 'data   : ' + this.$data) //undefined
        console.log('%c%s', 'color:red', '新值: ' + newVal, '旧值: ' + oldVal)
      },
    ],
  },
  beforeCreate: function () {
    
    
    console.group('------beforeCreate创建前状态------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //undefined
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  created: function () {
    
    
    console.group('------created创建完毕状态------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //已被初始化
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message) //已被初始化
  },
  beforeMount: function () {
    
    
    console.group('------beforeMount挂载前状态------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //已被初始化
    console.log('%c%s', 'color:red', 'message: ' + this.message) //已被初始化
  },
  mounted: function () {
    
    
    console.group('------mounted 挂载结束状态------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //已被初始化
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //已被初始化
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message) //已被初始化
  },
  beforeUpdate: function () {
    
    
    console.group('beforeUpdate 更新前状态===============》')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el)
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data)
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  updated: function () {
    
    
    console.group('updated 更新完成状态===============》')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el)
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data)
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  beforeDestroy: function () {
    
    
    console.group('beforeDestroy 销毁前状态===============》')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el)
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data)
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  destroyed: function () {
    
    
    console.group('destroyed 销毁完成状态===============》')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el)
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data)
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  errorCaptured(err, vm, info) {
    
    
    console.group('errorCaptured 捕获子孙组件的错误阶段===============》')
    console.log(`错误返回: ${err.toString()}\n在哪个钩子发生的错误: ${info}\nvue实例: ${vm}`)
  },
  methods: {
    
    
    testListSomeMethod() {
    
    
      console.log('通过watch调用该testListSomeMethod方法')
    },
    someMethod() {
    
    
      console.log('通过watch调用该someMethod方法')
    },
    homePageShowTap() {
    
    
      this.isHomePageShow = !this.isHomePageShow
    },
    showTap() {
    
    
      this.$destroy('home')
    },
  },
}
</script>

homePage subpage

<template>
  <div>
    <h3 style="color: red">子页面</h3>
    <div>{
    
    {
    
     message }}</div>
  </div>
</template>

<script>
export default {
    
    
  name: 'HomePage',
  data() {
    
    
    return {
    
    
      message: '这里是子组件homePage',
    }
  },
  beforeCreate: function () {
    
    
    console.group('------子组件beforeCreate创建前状态------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //undefined
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  created: function () {
    
    
    messageTest = '制造错误触发errorCaptured'
    console.group('------子组件created创建完毕状态------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //已被初始化
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message) //已被初始化
  },
  beforeMount: function () {
    
    
    console.group('------子组件beforeMount挂载前状态------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //已被初始化
    console.log('%c%s', 'color:red', 'message: ' + this.message) //已被初始化
  },
  mounted: function () {
    
    
    console.group('------子组件mounted 挂载结束状态------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //已被初始化
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //已被初始化
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message) //已被初始化
  },
  beforeUpdate: function () {
    
    
    console.group('子组件beforeUpdate 更新前状态===============》')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el)
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data)
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  updated: function () {
    
    
    console.group('子组件updated 更新完成状态===============》')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el)
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data)
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  beforeDestroy: function () {
    
    
    console.group('子组件beforeDestroy 销毁前状态===============》')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el)
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data)
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  destroyed: function () {
    
    
    console.group('子组件destroyed 销毁完成状态===============》')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el)
    console.dir(this.$el)
    console.log('%c%s', 'color:red', 'data   : ' + this.$data)
    console.dir(this.$data)
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  activated() {
    
    
    console.group('------activated缓存阶段,进入组件------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //undefined
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
  deactivated() {
    
    
    console.group('------activated缓存阶段,离开或停用当前组件------')
    console.log('%c%s', 'color:red', 'el     : ' + this.$el) //undefined
    console.log('%c%s', 'color:red', 'data   : ' + this.$data) //undefined
    console.log('%c%s', 'color:red', 'message: ' + this.message)
  },
}
</script>

<style  scoped>
</style>

The screenshot of the console, the printing order is as follows:insert image description here

First of all, beforeCreatebefore the creation, the current component instance has not been created, and it is used to create the development initialization task

Then watchdata monitoring, the current watch set immediate to true, the callback will be called immediately after the monitoring starts, the default is false

After createdthe creation is completed, our el, that is, the Dom element is still not available in this state, but we can already get the data, which means that the data has been loaded in, and it is usually createdused to send asynchronous data here ask

Before beforeMountmounting, the DOM node is not created, rendering and updating are not performed , so el still cannot get it before

Then computedcalculate the attribute, which can be a function or an object { {get,set}}, just a general function; can’t write set, suitable for a value affected by multiple data, and generally returns the result; has a cache attribute, multiple times in the template The use in will only be calculated once;


//If there are sub-components
, then sub-components, beforeCreate
then sub-components, create
and then sub-components, errorCapturedwhen the errors of sub-components are captured, it prompts where there is a problem with sub-components, then sub-
components, beforeMount
then sub-components, and beforeMount
then sub-componentsactivated


Finally, mountedthe mounting is completed, and the DOM node is created. Usually, you can use $refsto $elget the DOM node , so you can get el at this stage. We can use console.dir to print the attributes of some elements we need.

Then in the update phase, there is the following code on the vue page

 <a-input v-model="message" style="width: 120px"></a-input>
 <div>{
    
    {
    
     message }}</div>
  <h3 style="color: red">csdn博主:{
    
    {
    
     csdnName }}</h3>

insert image description here
Then we enter and change the message data in the input box, the screenshot is as follows
insert image description here


//If there is a calculated attribute , watch
it will enter watchthe data monitoring state, which can be a function or an object { {handler,immediate,deep}}; the default initialization will not be executed unless immediate is set to true; it is suitable for one value to affect multiple data, execute Multiple operations that may not return any results; suitable for asynchronous or expensive operations


Whenever we change page elements, we will enter the update phase, which is the two states of beforeUpdate and updated.
beforeUpdateis before the update, usually used to get the various states before the update
updateis after the update, all the states are up to date


If there are subcomponents, enter and leave (deactivate) the subcomponent sequence.
insert image description here
When clicking the hide/display subcomponent button,
insert image description here
first enter the parent component, then enter the subcomponent , then enter the subcomponent, beforeUpdate
then enter the subcomponent, and then enter the parent componentsactivated
beforeDestroy
destroyed
activated


Then in the unloading (destroying) phase, there is a new code in the vue parent

//在template代码块增加如下按钮
  <a-button @click="showtap">点击卸载</a-button>
 //在script增加一个方法
  methods: {
    
    
    showtap() {
    
    
      this.$destroy('home')
    },
  },

The screenshot after clicking the uninstall button is as follows:insert image description here

beforeDestroyThe state before destruction, elements and data can be printed out before destruction, usually used for timers or unsubscribing, etc., and the component instance still exists at this time .


//If there is a subcomponent
, then enter the state before activated
the subcomponent is destroyed , and then the subcomponent destroys the completed statebeforeDestroy
destroyed


destroyedThe status of the completion of destruction can also be printed out, the component has been destroyed, and the component instance does not exist at this time

beforeDestroyand destroyed, are the life cycles that will only be called when we leave this component.

4. Summary

life cycle:

Also known as: life cycle callback function, life cycle function, life cycle hook.
What it is: some functions with special names that Vue calls for us at critical moments.
The name of the life cycle function cannot be changed, but the specific content of the function is written by the programmer according to the requirements.
The this in the lifecycle function points to the vm or component instance object.
 
Commonly used lifecycle hooks:

mounted: send ajax requests, start timers, bind custom events, subscribe to messages, etc. [initialization operations].
beforeDestroy: Clear timers, unbind custom events, unsubscribe messages, etc. [finishing work].
 
About destroying the Vue instance
After destruction, you can't see any information with the help of Vue developer tools.
Custom events will be invalid after destruction, but native DOM events are still valid.
Generally, the data will not be manipulated in beforeDestroy, because even if the data is manipulated, the update process will not be triggered again.
 
Official website : https://cn.vuejs.org/api/options-lifecycle.html#beforecreate

insert image description here

Guess you like

Origin blog.csdn.net/weixin_43861689/article/details/129714989