版本:vue2.X、ant design vue 1.7.8
答:vue的生命周期就是一个组件从创建开始的初始化、挂载、更新等步骤后,最后被卸载的过程;
相当于现实生活中拼图游戏,
先在初始化阶段准备拼图的图板、零散的拼图;
在挂载的阶段把拼图一个一个的拼凑成目标的图案;
在更新阶段相当于把拼图里有部分拼凑错图的扣出来或额外diy新的图放到需要放的地方;
在卸载阶段相当于把拼凑好的拼图欣赏完后再拆散收起来的过程
挂载阶段:
beforeCreate //数据检测和数据代理的创建之前
created //数据检测和数据代理的创建创建完毕
beforeMount //挂载之前
mounted //挂载完毕
更新阶段:
beforeUpdate //更新之前
update //更新完毕
卸载(销毁)阶段:
beforeDestroy //卸载之前
destroyed //卸载完毕
缓存(KeepAlive)阶段:
activated //进入该组件的页面
deactivated //停用或离开时(但组件并未被销毁)
错误提示阶段:
errorCaptured //捕获子孙组件的错误时
errorHandler //指定组件在渲染和观察期间未捕获错误处理函数
computed //计算属性
watch //数据监听
<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子页面
<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>
首先是beforeCreate
创建之前,当前组件实例还未创建,通过用于创建开发初始化任务
再是watch
数据监听,当前watch设置了immediate为true,该回调将会在侦听开始之后立即调用,默认是false
再是created
创建完毕,在这个状态中我们的el,也就是Dom元素依旧是拿不到的,但是我们已经可以拿到data了,这意味着 created
已经将数据加载进来了 ,通常这里用于发送异步数据请求
再是beforeMount
挂载之前,DOM节点未创建,未执行渲染、更新,所以在这之前el还是拿不到
再是computed
计算属性,可为函数或对象{{get,set}},一般函数即可;不会书写set,适合一个值受多个数据影响,一般会返回结果;具备缓存属性,多次在模板中使用只会计算一次;
//如果有子级组件
再是子组件beforeCreate
再是子组件create
再是子组件errorCaptured
捕获子孙组件的错误时,提示了子组件哪里有问题
再是子组件beforeMount
再是子组件beforeMount
再是子组件activated
最后是mounted
挂载完毕,DOM节点创建完成,通常可以使用$refs
、$el
来获取DOM节点,所以此阶段可以拿到el了。我们可以用console.dir去打印一些我们需要的元素的属性。
然后在更新阶段,在vue页面有如下代码
<a-input v-model="message" style="width: 120px"></a-input>
<div>{{ message }}</div>
<h3 style="color: red">csdn博主:{{ csdnName }}</h3>
然后我们在input输入框输入更改message数据,截图如下
//如果有计算属性watch
则会进入watch
数据监听状态,可为函数或对象{{handler,immediate,deep}};默认初始化不会执行,除非将immediate设置为true;适合一个值影响多个数据,执行多个操作,可不返回任何结果;适合执行异步或开销比较大的操作
每当我们去改变页面元素的时候,就会进入更新阶段,也就是beforeUpdate,updated这两个状态。
beforeUpdate
是更新前,通常用于获取更新前的各种状态
update
是更新后,所有状态都是最新的
如果有子组件,则进行进入、离开(停用)子组件顺序
当点击隐藏/显示子组件按钮
先是进入父级组件beforeUpdate
再是进入子组件activated
再是进入子组件beforeDestroy
再是进入子组件destroyed
再是进入父级组件activated
然后在卸载(销毁)阶段,在vue父级新有下代码
//在template代码块增加如下按钮
<a-button @click="showtap">点击卸载</a-button>
//在script增加一个方法
methods: {
showtap() {
this.$destroy('home')
},
},
beforeDestroy
销毁前状态,在销毁前元素、data都是可以打印出来的,通常用于定时器或取消订阅等,此时组件实例仍然存在。
//如果有子组件
则进入activated
再是子组件beforeDestroy
销毁前状态
再是子组件destroyed
销毁完成状态
destroyed
销毁完成的状态也是什么都可以打印出来,组件已销毁,此时组件实例不存在
beforeDestroy
和destroyed
,都是我们离开这个组件才会被调用的生命周期。
生命周期:
又名:生命周期回调函数、生命周期函数、生命周期钩子。
是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
生命周期函数中的this指向是vm 或 组件实例对象。
常用的生命周期钩子:mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
关于销毁Vue实例
销毁后借助Vue开发者工具看不到任何信息。
销毁后自定义事件会失效,但原生DOM事件依然有效。
一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
官网:https://cn.vuejs.org/api/options-lifecycle.html#beforecreate