Vue中组件生命周期过程详解

2020年06月23日 阅读数:33
这篇文章主要向大家介绍Vue中组件生命周期过程详解,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

1、什么是生命周期?

Vue中的生命周期是指:组件从建立到销毁的一个过程,在这过程当中,咱们在每一个特定阶段会触发一些方法(这些方法具有一些功能),咱们给这些方法起了名字叫作(生命周期钩子函数/组件钩子)javascript

2、为何要学习生命周期

咱们须要在生命周期钩子中实现项目功能,那么咱们必需要知道每个钩子函数的具体用途。html

3、生命周期指的是组件的生命周期。

Vue的生命周期分为三个阶段,分别为:初始化,运行中,销毁,一共8个钩子;java

生命周期钩子函数不容许写成箭头函数web

  • 全部的生命周期钩子自动绑定 this 上下文到实例中,所以你能够访问数据,对属性和方法进行运算。若是使用箭头函数来定义一个生命周期方法 (例如 created: () => this.fetchTodos()),箭头函数this绑定了父上下文,所以 this 与你期待的 Vue 实例不一样,this.fetchTodos 的行为未定义。

4、生命周期分阶段详解

Vue官网对生命周期的详细示意图
在这里插入图片描述
整个生命周期全部钩子函数以下:算法

<body>
   <div id="app">
      <Test></Test>
   </div>
   
   <template id="test">
      <div>
         <h3>这是Test组件</h3>
         <p> {{ msg }} </p>
      </div>
   </template>
  
</body>
<script>
new Vue({
    el:'#app',

    components:{
      'Test':{
          template:"#test",
          data(){
            return {
               msg:'Hello 你好'
            }
         },

         beforeCreate(){
            console.log('1-beforeCreate');
            console.log('data',this.msg);
            console.log('真实的dom:',document.querySelector('p'));

            // fetch('./data.json')
            // .then(res => res.json())
            // .then(data => this.msg = data)
            // .catch(error=>console.log(error))
         },

         created(){
            console.log('2-created');
            console.log("data",this.msg);
            console.log('真实的dom:',document.querySelector('p'));

             // fetch('./data.json')
             // .then(res=>res.json())
             // .then(data=>this.msg=data)
             // .catch(error=>console.log(error))
            },

         beforeMount () {
            console.log('3-beforeMount');
            console.log('data',this.msg);
            console.log('真实的dom',document.querySelector('p'));

             //  fetch('./data.json')
             //  .then(res => res.json())
             //  .then(data => this.msg=data)
             //  .catch(error => console.log(error))
             },
         mounted () {
            console.log('4-mounted');
            console.log('data',this.msg);
            console.log('真实的dom',document.querySelector('p'));

            fetch('./data.json')
            .then(res => res.json())
            .then(data => this.msg = data)
            .catch(error => console.log(error))
         },
         
         // ----------------------- 运行中-----------------------
        beforeUpdate () {
           console.log('beforeUpdate');
          //经过页面数据查看是否渲染 console.log('data',$refs.msg.innerHTML);
           console.log('真实的dom',document.querySelector('p'))
         },

        updated () {
           console.log('update');
           //经过页面数据查看是否渲染 console.log('data',$refs.msg.innerHTML);
           console.log('真实的dom',document.querySelector('p'))
         }
         
    // ----------------------- 销毁阶段----------------------- 
        /*
	      beforeDestroy () {
	         console.log('beforeDestroy')
	        },
	       
	       destroyed () {
	         console.log('destroyed')
	         }
	   */
       }
    }
 })

</script>

初始化阶段

** 初始化阶段的4个钩子: beforeCreate、created、beforeMount、mounted;**json

beforeCreate:阶段
 beforeCreate () {
        console.log('1-beforeCreate');
        console.log('data',this.msg);//undefined
        console.log('真实的dom:',document.querySelector('p'));//null

        fetch('./data.json')
        .then(res => res.json())
        .then(data => this.msg = data)
        .catch(error => console.log(error))
     }

在这里插入图片描述

  • 一、组件建立前触发,目的是为组件的 生命周期和组件中的事件作准备;
  • 二、没有得到数据,真实dom也没有渲染出来
  • 三、在此阶段内能够进行数据请求,提供一次修改数据的机会
  • 四、此阶段执行一次
created:阶段

 created () {
    console.log('2-created');
    console.log("data",this.msg);
    console.log('真实的dom:',document.querySelector('p'));

    fetch('./data.json')
    .then(res => res.json())
    .then(data => this.msg = data)
    .catch(erro r=> console.log(error))
 }

在这里插入图片描述

  • 一、组件建立结束
  • 二、数据能够拿到了
  • 三、能够进行数据请求,提供一次修改数据的机会
  • 四、该过程执行一次
beforeMount:阶段
beforeMount () {
            console.log('3-beforeMount');
            console.log('data',this.msg);
            console.log('真实的dom',document.querySelector('p'));

            fetch('./data.json')
             .then(res => res.json())
             .then(data => this.msg=data)
             .catch(error => console.log(error))
         },

在这里插入图片描述

  • 一、组件挂载前
  • 二、该阶段任务:
    • 判断el,判断template;
    • 若是el没有,那么咱们须要手动挂载,若是有,那麽判断template;
    • 若是template有,那么进行render函数,若是template没有,那么经过outHTML手动书写模板;
  • 三、数据能够得到,可是真实dom尚未渲染
  • 四、能够进行数据请求,也提供了一次数据修改的机会
mounted:阶段
mounted () {
    console.log('4-mounted');
    console.log('data',this.msg);
    console.log('真实的dom',document.querySelector('p'));

    fetch('./data.json')
    .then(res => res.json())
    .then(data => this.msg = data)
    .catch(error => console.log(error))
 }
 

在这里插入图片描述

  • 一、组件挂载结束
  • 二、数据得到,真实dom也得到了
  • 三、能够进行数据请求,也能够修改数据
  • 四、执行一次
  • 五、能够进行真实dom的操做了

总结:数据请求咱们通常写在created钩子中,第三方库的实例化咱们通常写在mounted钩子中;app

运行中阶段

运行中阶段有两个钩子:beforeUpdate、updated;
运行中阶段触发条件是:数据更新dom

beforeUpdate:阶段

数据更新前阶段svg

 beforeUpdate () {

       console.log('beforeUpdate');
       //从新渲染 VDOM , 而后经过diff算法比较两次vdom,生成patch 补丁对象
       console.log('=即将更新渲染=');
       console.log('页面data',this.$refs.msg.innerHTML);
       console.log('真实的dom',document.querySelector('p'))
    },
    1. 更新前
    1. 从新渲染 VDOM , 而后经过diff算法比较两次vdom,生成patch 补丁对象,还未渲染到页面
    1. 这个钩子函数更多的是内部进行一些操做
    1. 能够触发屡次,只要数据更新就会触发
 updated () {
      console.log('update');
      console.log('==更新成功==');
      console.log('data',this.$refs.msg.innerHTML);
      console.log('真实的dom',document.querySelector('p'))
   }
    1. 数据更新结束
    1. 真实dom获得了,数据也获得了( 更新后的 )
    1. 能够用于动态数据获取( 第三方库实例化 )
    1. 能够触发屡次,只要数据更新就会触发
      在这里插入图片描述

销毁阶段

销毁阶段也是有两个钩子:beforeDestroy、destroyed.这两个钩子用法基本相同。
这两个钩子用法:计时器的关闭 第三方实例的删除
组件销毁须要触发条件:函数

  • 一、能够经过组件外部定义开关控制组件的销毁
  • 二、组件内部定义$destroy()的方法,经过调用该方法控制组件销毁。

例子1:经过组件外部定义开关销毁组件

<body>
   <div id="app">
      <Test v-if="flag"></Test>
       <button  @click="flag=!flag">销毁</button>
     

   </div>
   <template id="test">
      <div>
         <h3>这是Test组件</h3>
         <p ref="msg"> {{ msg }} </p>
      </div>
   </template>
      
</body>


 new Vue({
      el:"#app",
      data:{
         flag:true,
      },

      components:{
        'Test':{
            template:'#test',
            data(){
                  return {
                     msg:'Hello 你好'
                  }
            },

            beforeDestroy () {
                  console.log('beforeDestroy')
            },
            
            destroyed () {
               console.log('destroyed')
            }
         }
      }
   })

例子2:组件内部调用$destroy方法销毁组件

<body>
   <div id="app">
      <Test v-if="flag"></Test>
   </div>
   <template id="test">
      <div>
         <h3>这是Test组件</h3>
         <p ref="msg"> {{ msg }} </p>
         <button @click = "clear">销毁</button>
      </div>
   </template>
      
</body>
new Vue({
      el:"#app",

      components:{
        'Test':{
            template:'#test',
            data(){
                  return {
                     msg:'Hello 你好'
                  }
            },

            methods:{
            //内部经过$destroy方法删除自身组件,触发destroy生命钩子函数
               clear() {
                  this.$destroy();
               }
            },
            beforeDestroy () {
                console.log('beforeDestroy');
            //组件已经销毁,可是渲染出的真实dom结构未被销毁,手动销毁
                document.querySelector('#app').remove()

            },
            
            destroyed () {
               console.log('destroyed')
            }
         }
      }
   })

对比: 内部销毁 vs 外部销毁

  • 外部销毁不只能销毁组件,也能销毁该组件的dom结构
  • 内部销毁只能销毁组件,不能销毁组件的dom结构,dom结构须要手动销毁

以上仅为我的观点