Vue笔记(Vue生命周期 11个钩子)

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

19669186-4c417cbdf6c30add.png

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

生命周期钩子的11个阶段:

创建:
beforeCreate -- 数据初始化前
created -- 数据初始化之后
beforeMount -- 数据准备渲染
Mounted -- 数据渲染完成
运行:
beforeUpdata -- 数据更新前
updated -- 数据更新
销毁:
beforeDestroy -- 结束之前执行
destroyed -- 执行结束
缓存:
activated -- 组件激活时执行
deactivated -- 组件停用时执行
错误处理
errorCaptured -- 错误处理机制


构建vue实例

            var vm = new Vue({
                el:"#app",
                data:{
                    circle:"生命周期"
                },

beforeCreate -- 数据初始化前

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

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

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

created -- 数据初始化之后

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

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

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

beforeMount -- 数据准备渲染

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

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

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

Mounted -- 数据渲染完成

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

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

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

beforeUpdata -- 数据更新前

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

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

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

updated -- 数据更新

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

数据更新已经完成

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

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

image.png

点击更新后 updated :

image.png

image.png

beforeDestroy -- 结束之前执行

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

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

destroyed -- 执行结束

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

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

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

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

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

子组件A内容
<template>
    <div>
        <div>componentA</div>
        <button @click="show=!show" >componentA事件</button>
        <div v-if='show'>componentA-2</div>
        <div v-else>componentA-1</div>
    </div>
</template>
<script>
    export default {
        name: 'componentA',
        comments: {},
        data() {
            return {
                show: true,
                circle:'生命周期'
            }
        },
        activated() {
            console.group("activated 组件激活时执行 ");
            console.log("%c%s","color:pink",this);//this指向vue的实例
            console.log(this.$el);//<div id="app" >...</div>
            console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
            console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
            console.log("%c%s","color:blue","message:"+this.circle);//message:undefined
        },      
        deactivated() {
            console.group("deactivated 组件停用时执行");
            console.log("%c%s","color:pink",this);//this指向vue的实例
            console.log(this.$el);//<div id="app" >...</div>
            console.log("%c%s","color:skyblue","el:"+this.$el);//el:[object HTMLDivElement]
            console.log("%c%s","color:green","data:"+this.$data);//data:[object Object]
            console.log("%c%s","color:blue","message:"+this.circle);//message:undefined
        }
    }
</script>
<style>
</style>
子组件B内容
<template>
    <div>
        <div>componentB</div>
    </div>
</template>
<script>
    export default {
        name: 'componentB',
        compnents: {},
        data() {
            return {}
        }
    }
</script>
<style>
</style>
父组件内容
<template>
    <div id="box">

        <button @click="active='componentA'">componentA</button>
        <button @click="active='componentB'">componentB</button>
        
        <keep-alive>
            <component :is='active' ></component>
        </keep-alive>
        
    </div>
</template>
<script>
    import Vue from 'vue'
    import componentA from '@/components/componentA'
    import componentB from '@/components/componentB'

    export default{
        
        components:{
            componentA,
            componentB
        },
        
        data(){
            return{
                active:'componentB'
            }
        }
    }
</script>
<style>
</style>

输出

SDGIF_Rusult_2.gif

这里看到当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中使用

import Vue from 'vue'//引入Vue框架

import router from './router'//引入路由

Vue.config.errorHandler = function (err, vm, info) {
      // #处理错误信息, 进行错误上报
      // #err错误对象
      // #vm Vue实例
      // #`info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
      // #只在 2.2.0+ 可用
    console.log("%c%s","color:red","#err错误对象:",err)
    console.log("%c%s","color:blue","#vm Vue实例:",vm)
    console.log("%c%s","color:green","#`info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子:",info)
}   

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

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

输出

image.png

当这个钩子检测到组件中发生错误时就被调用。通过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:在缓存里能用来代替beforedestroydestroy
errorCaptured :能快速找到报错的组件位置,还能解决满屏红等视觉冲击

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

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345