Vue核心⑬(生命周期)

举报
十八岁讨厌编程 发表于 2022/08/05 22:43:24 2022/08/05
【摘要】 文章目录 生命周期引入挂载流程更新流程销毁流程生命周期总结 生命周期引入 生命周期: 又名:生命周期回调函数、生命周期函数、生命周期钩子。是什么:Vue在关键时刻帮我们调用的一些特殊名称...

生命周期引入

生命周期

  • 又名:生命周期回调函数、生命周期函数、生命周期钩子。
  • 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
  • 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
  • 生命周期函数中的this指向是 vm 或 组件实例对象。

例如我们现在有一个需求,页面上显示一行文字,并且动态的改变它的透明度。

代码如下:

	<body>
		<!-- 准备好一个容器-->
		<div id="root">
		    <!--<h2 :style="{opacity:opacity}">欢迎学习Vue</h2>  因为重名所以可以写成对象的简写形式-->
			<h2 :style="{opacity}">欢迎学习Vue</h2>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
		
		 new Vue({
			el:'#root',
			data:{
				opacity:1
			},
			methods: {
				
			},


		//通过外部的定时器实现(不推荐)
		setInterval(() => {
			vm.opacity -= 0.01
			if(vm.opacity <= 0) vm.opacity = 1
		},16) 
	</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

注意:

  • {opacity}使用了对象的简写形式
  • 因为定时器在vm的外面,所以我们要获取opacity就可以通过数据代理从vm上获得
  • 因为小数的运算在js中是不准确的,所以我们没有写成vm.opacity === 0,而是写成vm.opacity <= 0

这样写可以实现功能,但是Vue实例与处理逻辑分开了,且处理逻辑还在操作Vue中的数据。也就是说从功能上来讲两者连在一起,但是从代码层面上来讲,他们俩是割裂开的。我们希望将这个逻辑放入到Vue中去。

此时我们就可以借助生命周期函数。在Vue完成模板的解析并把真实DOM全部挂载到页面上完毕之后,会调用一个mounted()函数,我们可以借助它来完成这个案例:

挂载就是第一次把真实DOM放入到页面中

	<body>
		<!-- 准备好一个容器-->
		<div id="root">
			<h2 :style="{opacity}">欢迎学习Vue</h2>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
		
		 new Vue({
			el:'#root',
			data:{
				opacity:1
			},
			methods: {
				
			},
			//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
			mounted(){
				console.log('mounted',this)
				setInterval(() => {
					this.opacity -= 0.01
					if(this.opacity <= 0) this.opacity = 1
				},16)
			},
		})

		//通过外部的定时器实现(不推荐)
		/* setInterval(() => {
			vm.opacity -= 0.01
			if(vm.opacity <= 0) vm.opacity = 1
		},16) */
	</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

mounted中Vue已经把它的this维护成了vm。所以上面的代码中使用箭头函数的时候,this往外寻找就是vm。

挂载流程

下图中红圈mounted之前的部分都属于挂载部分。

红色圆框对应着生命周期函数
在这里插入图片描述
其中有几个注意点:
在这里插入图片描述
这个地方的create不是指的vm创建,而是数据监测、数据代理的创建

在这里插入图片描述
此处是可以进行DOM操作的,页面的效果也会发生变化。但是紧随其后
在这里插入图片描述
也就是说不管你此时如何操作DOM,当Vue把虚拟DOM转为真实DOM之后,你原来操作的效果都会消失。

template是什么?
例如我们现在有一段代码:

	<body>
		<!-- 准备好一个容器-->
		<div id="root" :x="n">
			<h2>当前的n值是:{{n}}</h2>
			<button @click="add">点我n+1</button>
		</div>
	</body>
		<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		new Vue({
			el:'#root',
			data:{
				n:1
			},
			methods: {
				add(){
					console.log('add')
					this.n++
				},
			},

		})
	</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

我们可以借助template让容器里面什么都不写:

	<body>
		<!-- 准备好一个容器-->
		<div id="root" :x="n">

		</div>
	</body>
		<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		new Vue({
			el:'#root',
			template:`
			 	<div>
			 		<h2>当前的n值是:{{n}}</h2>
			 		<button @click="add">点我n+1</button>
			 	</div>
			 `,
			data:{
				n:1
			},
			methods: {
				add(){
					console.log('add')
					this.n++
				},
			},

		})
	</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

注意:

  • template后面跟字符串
  • 如果不想全写在一行就要使用模板字符串,否则报错
  • Vue会直接把template当作模板执行后面的步骤(解析生成真实DOM·····)。
  • template里面只能有一个根元素,所以我们把他用div包裹(不要使用<template>标签去包裹,会报错)
  • 注意:

在使用了template之后,我们的网页:
在这里插入图片描述
不使用template:
在这里插入图片描述
也就是说如果使用template,Vue会将整个绿色框里的东西替换掉整个红色框里的东西:
在这里插入图片描述

在这里插入图片描述
在这一步骤中我们可以看到Vue将真实的DOM节点在$el中存了一份,再去插入到页面之中。为什么这么做呢?
在前面我们说过Vue在进行新的虚拟DOM和旧的虚拟DOM比较的时候,会出现有的元素可以复用的情况。既然要复用我们就要有这个之前的元素才能去复用,所以说这个地方要存一份备用。

更新流程

在这里插入图片描述

销毁流程

在这里插入图片描述
当我们执行了vm.$destroy()之后,代表着Vue进入了销毁流程。不过我们要注意的是vm销毁了,但他的工作成果还在,也就是说页面还是正常显示的。只是说没有人帮我们继续管理DOM。

在这里插入图片描述
注意:
①这里的其他实例代表的是组件
②解绑的是所有的自定义事件监听器,而原生的DOM事件监听器仍是有效的

例如:

	<body>
		<!-- 准备好一个容器-->
		<div id="root" :x="n">
			<h2>当前的n值是:{{n}}</h2>
			<button @click="add">点我n+1</button>
			<button @click="bye">点我销毁vm</button>
		</div>
	</body>
	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		new Vue({
			el:'#root',
			data:{
				n:1
			},
			methods: {
				add(){
					console.log('add')
					this.n++
				},
				bye(){
					console.log('bye')
					this.$destroy()
				}
			},
		})
	</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

在这里插入图片描述
当我们点击了销毁按钮之后,页面还是这样没有变。不过当我们再次去点击+1的时候页面是没有反应的,同时打开Vue开发者工具我们发现啥都没有了:
在这里插入图片描述

在这里插入图片描述
意思是说销毁监听,子组件,和事件监听器

在这里插入图片描述
在beforeDestroy这一部分,图中的文字告诉我们data、methods、指令等都是可用的。我们可以试一下:

	<body>
		<!-- 准备好一个容器-->
		<div id="root" :x="n">
			<h2>当前的n值是:{{n}}</h2>
			<button @click="add">点我n+1</button>
			<button @click="bye">点我销毁vm</button>
		</div>
	</body>
	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		new Vue({
			el:'#root',
			data:{
				n:1
			},
			methods: {
				add(){
					console.log('add')
					this.n++
				},
				bye(){
					console.log('bye')
					this.$destroy()
				}
			},
			beforeDestroy() {
				console.log('beforeDestroy')
				this.add()
			},
			destroyed() {
				console.log('destroyed')
			},
		})
	</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

结果:
在这里插入图片描述
结果我们发现add()确实可以用,但是页面并没有发生变化。也就是说在beforeDestroy这一阶段,所有对数据的修改不会再发生更新。

生命周期总结

生命周期函数一共是8个,我们可以将它们看作4对:

  • 将要创建 / 创建完毕
  • 将要挂载 / 挂载完毕
  • 将要更新 / 更新完毕
  • 将要销毁 / 销毁完毕

对应着:

  • beforeCreate() / created()
  • beforeMount() / mounted()
  • beforeUpdate() / updated()
  • beforeDestroy() / destroyed()

在这里插入图片描述

接下来我们在开头的案例上添加一个需求:添加一个按键,点击之后透明度变化停止。

代码如下:

	<body>
		<!-- 准备好一个容器-->
		<div id="root">
			<h2 :style="{opacity}">欢迎学习Vue</h2>
			<button @click="stop">点我停止变换</button>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		 new Vue({
			el:'#root',
			data:{
				opacity:1
			},
			methods: {
				stop(){
					clearInterval(this.timer)
				}
			},
			//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
			mounted(){
				console.log('mounted',this)
				this.timer = setInterval(() => {
					console.log('setInterval')
					this.opacity -= 0.01
					if(this.opacity <= 0) this.opacity = 1
				},16)
			},
		})

	</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

为了能让methods中的stop方法能访问到定时器,我们可以把定时器添加到vm身上。当然使用变量提升也是可以的。

如果我们再添加一个按钮:将透明度设置为1。代码如下:

	<body>
		<!-- 准备好一个容器-->
		<div id="root">
			<h2 :style="{opacity}">欢迎学习Vue</h2>
			<button @click="opacity = 1">透明度设置为1</button>
			<button @click="stop">点我停止变换</button>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		 new Vue({
			el:'#root',
			data:{
				opacity:1
			},
			methods: {
				stop(){
					clearInterval(this.timer)
				}
			},
			//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
			mounted(){
				console.log('mounted',this)
				this.timer = setInterval(() => {
					console.log('setInterval')
					this.opacity -= 0.01
					if(this.opacity <= 0) this.opacity = 1
				},16)
			},
		})

	</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

我们发现在点击停止变换之后,在点击透明度变化为1的按钮仍然是奏效的。

我们可以使用另外一种暴力的方法停止变换,使用$destroy():

	<body>
		<!-- 准备好一个容器-->
		<div id="root">
			<h2 :style="{opacity}">欢迎学习Vue</h2>
			<button @click="opacity = 1">透明度设置为1</button>
			<button @click="stop">点我停止变换</button>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		 new Vue({
			el:'#root',
			data:{
				opacity:1
			},
			methods: {
				stop(){
					this.$destroy()
				}
			},
			//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
			mounted(){
				console.log('mounted',this)
				this.timer = setInterval(() => {
					console.log('setInterval')
					this.opacity -= 0.01
					if(this.opacity <= 0) this.opacity = 1
				},16)
			},
			beforeDestroy() {
				clearInterval(this.timer)
			},
		})

	</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

不要想着在stop中去关闭计时器,如果vm是因为其他原因销毁(也就是说不是通过点击按钮),那么stop也就不会被调用,计时器也就不会被关闭。所以最好是把关闭定时器的操作放在beforeDestroy()中。

销毁vm后定时器仍然是在计时的,我们可以在beforeDestroy()中把它关掉

其实还有3个钩子在生命周期图中并没有体现,他们在特定的场景中才会使用到,例如:路由切换。

常用的生命周期钩子:

  • mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
  • beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

关于销毁Vue实例

  • 销毁后借助Vue开发者工具看不到任何信息。
  • 销毁后自定义事件会失效,但原生DOM事件依然有效。
  • 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

文章来源: blog.csdn.net,作者:十八岁讨厌编程,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/zyb18507175502/article/details/125275748

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。