zoukankan      html  css  js  c++  java
  • Vue 生命周期

    Vue

    Vue实例有一个完整的生命周期,也就是说从开始创建、初始化数据、编译模板、挂在DOM、渲染-更新-渲染、卸载等一系列过程,我们称为Vue 实例的生命周期(钩子函数)

    附上网上找的一张图解释
    当我们 new vue 的时候,这些函数就会自动执行


     

    生命周期钩子: 

    创建:
    beforeCreate -- 数据初始化前
    created -- 数据初始化之后
    beforeMount -- 数据准备渲染
    Mounted -- 数据渲染完成


    运行:
    beforeUpdata -- 数据更新前
    updated -- 数据更新

    销毁:
    beforeDestroy -- 结束之前执行
    destroyed -- 执行结束


    缓存:
    activated -- 组件激活时执行
    deactivated -- 组件停用时执行


    错误处理:
    errorCaptured -- 错误处理机制

    构建vue实例

    1 var vm = new Vue({
    2     el:"#app",
    3     data:{
    4         return{
    5             circle:"生命周期"
    6         }
    7     },
    8 })    

     

     beforeCreate -- 数据初始化前

    在实例初始化之后,数据观测和event|watcher事件配置之前使用,
    这个时期,this变量还不能使用,在data下面的数据和methods下面的方法,watcher中的事件都获取不到。

    可以在这里加一个loading事件,在实例加载的时候触

    1 beforeCreate(){
    2     console.group("beforeCreate 创建状态,初始化前");
    3     console.log("%c%s","color:pink",this);//this指向vue的实例
    4     console.log(this.$el);//undefined
    5     console.log("%c%s","color:skyblue","el:"+this.$el);//el:undefined
    6     console.log("%c%s","color:green","data:"+this.$data);//data:undefined
    7     console.log("%c%s","color:blue","message:"+this.circle);//message:undefined
    8 },


     

    created -- 数据初始化之后

    实例已经创建完成之后被调用,在这一步,实例已经完成以下的配置,数据观测,属性和方法的运算,event|watcher事件回调;但是,挂载阶段还没有开始,$el属性还不可见,这个时候可以操作vue实例中的数据和各种方法.但是还不能对DOM节点进行操作

    初始化完成时的事件写在这里,比如在这里结束loading事件,异步请求也可以在这里调用

    1 created(){
    2     console.group("created 创建状态,初始化后");
    3     console.log("%c%s","color:pink",this);//this指向vue的实例
    4     console.log("%c%s","color:skyblue","el:"+this.$el);//el:undefined
    5     console.log(this.$el);//undefined
    6     console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
    7     console.log("%c%s","color:blue","message:"+this.circle);//message:生命周期
    8 },


     

    beforeMount -- 数据准备渲染

    在挂载开始之前被调用,相关的render函数首次被调用

    这个时候可以获取到DOM节点,但还不能进行操作

    1 beforeMount(){
    2     console.group("beforeMount 创建状态,准备渲染");
    3     console.log("%c%s","color:pink",this);//this指向vue的实例
    4     console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
    5     console.log(this.$el);//<div id="app" >...</div>
    6     console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
    7     console.log("%c%s","color:blue","message:"+this.circle);//message:生命周期
    8 },


     

    Mounted -- 数据渲染完成

    el 被新创建的vm.$el替换并挂载到实例上去之后调用这个钩子,如果root实例挂载了一个文档内元素,当Mounted被调用时,vm. $el也在文档中。

    挂载完毕,DOM节点被渲染到文档中,DOM操作可以正常进行

    1 mounted(){
    2     console.group("mounted 创建状态,渲染完成");
    3     console.log("%c%s","color:pink",this);//this指向vue的实例
    4     console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
    5     console.log(this.$el);//<div id="app" >...</div>
    6     console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
    7     console.log("%c%s","color:blue","message:"+this.circle);//message:生命周期
    8 },


     

    beforeUpdata -- 数据更新前

    数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

    这里获取到data的数据是已经更新之后的数据,但还没渲染到文档流中,所以如果在这里获取DOM节点,得到的是未更新的数据。

    1 beforeUpdata(){
    2     console.group("beforeUpdata 执行状态,数据更新前");
    3     console.log("%c%s","color:pink",this);//this指向vue的实例
    4     console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
    5     console.log(this.$el);//<div id="app" >...</div>
    6     console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
    7     console.log("%c%s","color:blue","message:"+this.circle);//message:生命周期
    8 },

     

    updated -- 数据更新

    由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher取而代之。

    数据更新已经完成

    1 updated(){
    2     console.group("updated 执行状态,数据更新");
    3     console.log("%c%s","color:pink",this);//this指向vue的实例
    4     console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
    5     console.log(this.$el);//<div id="app" >...</div>
    6     console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
    7     console.log("%c%s","color:blue","message:"+this.circle);//message:生命周期
    8 },

    在这里绑定了一个按钮,改变数据
    更新前 beforeUpdata:

    点击更新后 updated :


     

    beforeDestroy -- 结束之前执行

    在实例销毁之前调用,实例仍然完全可用,这一步还可以用this来获取实例,一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的dom事件

    1 beforeDestroy(){
    2     console.group("beforeDestroy 销毁状态,销毁前执行");
    3     console.log("%c%s","color:pink",this);//this指向vue的实例
    4     console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
    5     console.log(this.$el);
    6     console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
    7     console.log("%c%s","color:blue","message:"+this.circle);//message:生命周期
    8 },


     

    destroyed -- 执行结束

    在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用

    1 destroyed(){
    2     console.group("destroyed 销毁状态,销毁完成");
    3     console.log("%c%s","color:pink",this);//this指向vue的实例
    4     console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
    5     console.log(this.$el);
    6     console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
    7     console.log("%c%s","color:blue","message:"+this.circle);//message:生命周期
    8 },


     

    activated 和 deactivated(组件激活时和停用时执行)

    这两个钩子需要配合配合<keep-alive><keep-alive/>来使用
    keep-alive的作用会缓存不活动的组件实例,而不是销毁它们。当组件在<keep-alive>内被切换,activated和deactivated这两个生命周期钩子函数将会被对应执行。

    在这里我搭建了一个脚手架,新建2个子组件,1个父组件

    子组件A

     1 <template>
     2     <div>
     3         <div>componentA</div>
     4         <button @click="show=!show" >componentA事件</button>
     5         <div v-if='show'>componentA-2</div>
     6         <div v-else>componentA-1</div>
     7     </div>
     8 </template>
     9 <script>
    10     export default {
    11         name: 'componentA',
    12         comments: {},
    13         data() {
    14             return {
    15                 show: true,
    16                 circle:'生命周期'
    17             }
    18         },
    19         activated() {
    20             console.group("activated 组件激活时执行 ");
    21             console.log("%c%s","color:pink",this);//this指向vue的实例
    22             console.log(this.$el);//<div id="app" >...</div>
    23             console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
    24             console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
    25             console.log("%c%s","color:blue","message:"+this.circle);//message:undefined
    26         },      
    27         deactivated() {
    28             console.group("deactivated 组件停用时执行");
    29             console.log("%c%s","color:pink",this);//this指向vue的实例
    30             console.log(this.$el);//<div id="app" >...</div>
    31             console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
    32             console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
    33             console.log("%c%s","color:blue","message:"+this.circle);//message:undefined
    34         }
    35     }
    36 </script>
    37 <style>
    38 </style>

    子组件B

     1 <template>
     2     <div>
     3         <div>componentB</div>
     4     </div>
     5 </template>
     6 <script>
     7     export default {
     8         name: 'componentB',
     9         compnents: {},
    10         data() {
    11             return {}
    12         }
    13     }
    14 </script>
    15 <style>
    16 </style>

    父组件

     1 <template>
     2     <div id="box">
     3 
     4         <button @click="active='componentA'">componentA</button>
     5         <button @click="active='componentB'">componentB</button>
     6         
     7         <keep-alive>
     8             <component :is='active' ></component>
     9         </keep-alive>
    10         
    11     </div>
    12 </template>
    13 <script>
    14     import Vue from 'vue'
    15     import componentA from '@/components/componentA'
    16     import componentB from '@/components/componentB'
    17 
    18     export default{
    19         
    20         components:{
    21             componentA,
    22             componentB
    23         },
    24         
    25         data(){
    26             return{
    27                 active:'componentB'
    28             }
    29         }
    30     }
    31 </script>
    32 <style>
    33 </style>

    输出:

    这里看到当A组件被点击激活时就触发activated钩子,点击B组件开启A组件关闭时deactivated钩子就触发执行。

    这里也能看出在keep-alive 里A组件的数据也被缓存起来,第二次触发的时候组件状态没有被重新改变


     

    errorCaptured -- 错误处理机制

    当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播

    1.默认情况下,如果全局的 config.errorHandler定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报
    如果一个组件的继承或父级从属链路中存在多个 errorCaptured 钩子,则它们将会被相同的错误逐个唤起。
    2.如果此 errorCaptured 钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的 config.errorHandler,不能捕获异步promise内部抛出的错误和自身的错误
    3.一个 errorCaptured 钩子能够返回 false 以阻止错误继续向上传播。本质上是说“这个错误已经被搞定了且应该被忽略”。它会阻止其它任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler

    在全局组件main.js中使用

     1 import Vue from 'vue'//引入Vue框架
     2 
     3 import router from './router'//引入路由
     4 
     5 Vue.config.errorHandler = function (err, vm, info) {
     6       // #处理错误信息, 进行错误上报
     7       // #err错误对象
     8       // #vm Vue实例
     9       // #`info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
    10       // #只在 2.2.0+ 可用
    11     console.log("%c%s","color:red","#err错误对象:",err)
    12     console.log("%c%s","color:blue","#vm Vue实例:",vm)
    13     console.log("%c%s","color:green","#`info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子:",info)
    14 }   

    然后在子组件中随意写入一个错误的信息

    1 mounted () {
    2     a // 直接定义一个错误的变量 a
    3 },

    输出

    当这个钩子检测到组件中发生错误时就被调用。通过err, vm, info这3个参数输出
    #err错误对象
    #vm Vue实例
    #info 是 Vue 特定的错误信息,比如错误所在的生命周期钩子


     

    总结一下:

    beforecreate:实例刚刚创建出来,data等属性方法都不能获取,loading事件可以放在这里。
    created:实例初始化完成,data等属性方法也初始化完成,但还没有开始编译,可以在这里结束loading,可以发送请求,拿数据。!注意一下,因为在这里还没有渲染页面,如果获取的数据过多,会造成有一段空白页面的延迟。
    beforemount :属性方法等已经编译完成,但还没挂载。
    mounted:这里所有的属性方法已经完成挂载。
    beforeUpdate:这个获取的数据是最新的值,但dom还是旧值
    updated:dom更新完成。
    beforedestroy:消亡前,用来清除定时器
    destroy:已消亡,也能用来清除定时器
    destroyed:实例完全销毁
    activated:可以用来初始化数据
    deactivated:在缓存里能用来代替beforedestroy和destroy
    errorCaptured :能快速找到报错的组件位置,还能解决满屏红等视觉冲击

    问题:
    如果当在子组件里写了一个定时器,子组件被销毁后,定时器还是会继续执行,所以要使用beforedestroy和destroyed,组件销毁后,清除定时器。

    <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们,所以在<keep-alive>中的所有组件不会触发<beforedestroy 和 destroyed 这两个钩子函数

    关于created 和 activated 的区别
    created 是页面初始化时才触发的函数,vue的优势在于不需要刷新或重启页面,所以created只会触发一次。而activated 是只要页面组件被激活就会执行

  • 相关阅读:
    第七周作业
    第六周作业
    第五周作业
    第四周作业
    第三周作业
    第二周作业
    求最大值及下标
    查找整数
    抓老鼠
    第五周作业
  • 原文地址:https://www.cnblogs.com/sanyekui/p/12682645.html
Copyright © 2011-2022 走看看