Vue -- 监视属性watch VS 计算属性computed & 箭头函数和普通函数的this指向问题

Posted Z && Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue -- 监视属性watch VS 计算属性computed & 箭头函数和普通函数的this指向问题相关的知识,希望对你有一定的参考价值。

1. 监视属性watch VS 计算属性computed


1.1 姓名案例: 计算属性实现

示例代码:

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8" />
	<title>姓名案例_计算属性实现</title>
	<!-- 引入Vue -->
	<script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
	<!-- 
			计算属性:
					1.定义:要用的属性不存在,要通过已有属性计算得来。
					2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
					3.get函数什么时候执行?
								(1).初次读取时会执行一次。
								(2).当依赖的数据发生改变时会被再次调用。
					4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
					5.备注:
							1.计算属性最终会出现在vm上,直接读取使用即可。
							2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
		 -->
	<!-- 准备好一个容器-->
	<div id="root">
		姓:<input type="text" v-model="firstName"> <br /><br />
		名:<input type="text" v-model="lastName"> <br /><br />
		全名:<span>{{fullName}}</span> <br /><br />
		<!-- 全名:<span>{{fullName}}</span> <br/><br/>
			全名:<span>{{fullName}}</span> <br/><br/>
			全名:<span>{{fullName}}</span> -->
	</div>
</body>

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

	const vm = new Vue({
		el: '#root',
		data: {
			firstName: '张',
			lastName: '三',
		},
		methods: {
			demo() {

			}
		},
		computed: {
			fullName: {
				//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
				//get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
				get() {
					console.log('get被调用了')
					// console.log(this) //此处的this是vm
					return this.firstName + '-' + this.lastName
				},
				//set什么时候调用? 当fullName被修改时。
				set(value) {
					console.log('set', value)
					const arr = value.split('-')
					this.firstName = arr[0]
					this.lastName = arr[1]
				}
			}
		}
	})
</script>

</html>

运行结果:


1.2 姓名案例: 监视属性实现

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8" />
	<title>姓名案例_watch实现</title>
	<!-- 引入Vue -->
	<script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
	<!-- 
				computed和watch之间的区别:
						1.computed能完成的功能,watch都可以完成。
						2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
				两个重要的小原则:
							1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
							2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,
								这样this的指向才是vm 或 组件实例对象。
		-->
	<!-- 准备好一个容器-->
	<div id="root">
		姓:<input type="text" v-model="firstName"> <br /><br />
		名:<input type="text" v-model="lastName"> <br /><br />
		全名:<span>{{fullName}}</span> <br /><br />
	</div>
</body>

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

	const vm = new Vue({
		el: '#root',
		data: {
			firstName: '张',
			lastName: '三',
			fullName: '张-三'
		},
		watch: {
			firstName(val) {
				setTimeout(() => {
					console.log(this)
					this.fullName = val + '-' + this.lastName
				}, 1000);
			},
			lastName(val) {
				this.fullName = this.firstName + '-' + val
			}
		}
	})
</script>

</html>

运行结果:


1.3 对比结论(箭头函数和普通函数的this指向问题):

computed和watch之间的区别:

  1. computed能完成的功能,watch都可以完成。
  2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作(因为watch用不到返回值是直接被监视的属性,而computed需要用到返回值)。

两个重要的小原则:

  1. 所被Vue管理的函数(Vue帮忙调用),最好写成普通函数(普通函数中的this代表它的直接调用者,如obj.fn(),fn的this指向就是obj。默认情况下,没有直接的调用者,this的指向为window),这样this的指向才是vm 或 组件实例对象。
  2. 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数=》JS引擎帮忙调用),最好写成箭头函数(箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值),这样this的指向才是vm 或 组件实例对象。

为什么被Vue管理的函数不可以写为箭头函数,它也是在Vue的构造方法里面定义的鸭?为啥它的this指向不是vm?

JS 代码分为 预解析阶段和执行阶段,在预解析阶段遇到函数声明会提前进行预解析,此时被Vue管理的箭头函数会在全局定义,因为 var vm = new Vue({…}) 这句代码在预解析阶段还没有被执行。当到了执行阶段此时的运行环境确实是新创建的 vm 对象。但是对于箭头函数来说,箭头函数中的 this 指向的是定义时的对象而不是函数运行时所在的对象,所以被Vue管理的箭头函数的this指向为全局的winodw,这一点与普通函数有很大的区别(普通函数是在函数调用时确定this指向)。



以上是关于Vue -- 监视属性watch VS 计算属性computed & 箭头函数和普通函数的this指向问题的主要内容,如果未能解决你的问题,请参考以下文章

vue的计算和监视属性,附一小实例

VUE:计算属性和监视

Vue--》计算属性与监视(侦听)属性的使用

VUE 计算属性 vs 侦听属性

Vue2.0学习—监视属性(三十五)

Vue.js watch监视属性