Vue中computed与watch

19 篇文章 10 订阅


区别

computedwatch
缓存支持缓存,只有依赖的数据发生了变化,才会重新计算不支持缓存,数据变,直接会触发相应的操作
异步不支持异步,当computed内有异步操作时无效,无法监听数据的变化支持异步
返回值函数必须用return返回最终的结果无返回值
应用场景多个属性计算出一个属性(购物车商品结算功能)一个属性改变多个属性的时候(搜索数据)

computed (计算属性)

  1. 属性的结果会被缓存,当computed中的函数所依赖的属性没有发生改变的时候,那么调用当前函数的时候结果会从缓存中读取,除非依赖的响应式属性变化时才会重新计算;

  2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化;

  3. computed中的函数必须用return返回最终的结果。computed更高效,优先使用;

  4. 当一个属性受多个属性影响的时候,一般用computed(购物车商品结算功能);

  5. 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法;

<template>
	<div>
		<p>{{fullName}}</p>
	</div>
</template>

<script type="text/ecmascript-6">
export default {
	name: "",
	data() {
		return {
			firstName: '张',
			lastName: '三'
		}
	},
	computed: {
		fullName() {
			return this.firstName + ' ' + this.lastName
		}
	}
}
</script>

vue3.x中:

<script>
import { ref, computed } from 'vue'
export default {
	setup () {
		const firstName = ref('张');
		const lastName = ref('三');

		// 计算属性
		const fullName = computed(() => {
			return firstName.value + ' ' + lastName.value
		})
		return { fullName }
	}
}
</script>

getter 与 setter

通过 getter\setter 实现对属性数据的显示和监视,计算属性存在缓存,多次读取只执行一次getter计算

<template>
	<div>
		<p>{{fullName}}</p>
	</div>
</template>

<script type="text/ecmascript-6">
export default {
	name: "",
	data() {
		return {
			firstName: '张',
			lastName: '三'
		}
	},
	computed: {
		fullName: {
		    // getter  对属性数据的显示
			get() {// 回调函数 当需要读取当前属性值时执行,根据相关数据计算并返回当前属性的值
				return this.firstName + ' ' + this.lastName
			},
		    // setter  对属性数据的监听
			set(val) { // 监听当前属性值的变化,当属性值发生变化时执行,更新相关的属性数据
				// val就是fullName的最新属性值
				console.log(val)
				const names = val.split(' ');
				console.log(names)
				this.firstName = names[0];
				this.lastName = names[1];
			}
		}
	}
}
</script>

watch(监听属性)

  1. 不支持缓存,数据变,直接会触发相应的操作;

  2. 支持异步

  3. 监听的函数接收两个参数,第一个参数是最新的值(newVal);第二个参数是输入之前的值(oldVal);

  4. 当一个属性影响多个属性的时候,一般使用watch(搜索数据);

  5. 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数,
      immediate:组件加载立即触发回调函数执行,
      deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。

<template>
	<div>
		<input type="text" v-model="name">
	</div>
</template>

<script type="text/ecmascript-6">
export default {
	name: "",
	data() {
		return {
			name: '张三'
		}
	},
	watch: {
		name(newVal, oldVal) {
			console.log(newVal, oldVal);
		}
	}
}
</script>

immediate(立即监听)

<template>
	<div>
		<p>FullName: {{fullName}}</p>
		<p>FirstName: <input type="text" v-model="firstName"></p>
	</div>
</template>

<script type="text/ecmascript-6">
export default {
	name: "",
	data() {
		return {
			firstName: '张',
			lastName: '三',
			fullName: ''
		}
	},
	watch: {
		firstName: {
			handler(newVal, oldVal) {
				this.fullName = newVal + this.lastName;
			},
			// 代表在wacth里声明了name这个方法之后立即先去执行handler方法
			immediate: true
		}
	}
}
</script>

deep(深度监听)

由于 Vue 不能检测到对象属性的添加或删除,这时候deep属性就派上用场了!

<template>
	<div>
		<p>obj.a: {{obj.a}}</p>
		<p>obj.a: <input type="text"
				   v-model="obj.a"></p>
	</div>
</template>

<script type="text/ecmascript-6">
export default {
	name: "",
	data() {
		return {
			obj: {
				a: 123
			}
		}
	},
	watch: {
		obj: {
			handler(newVal, oldVal) {
				console.log('obj.a changed');
			},
			// 深度监听对象
			deep: true
		}
	}
}
</script>

deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler。

优化,我们可以是使用字符串形式监听

<template>
	<div>
		<p>obj.a: {{obj.a}}</p>
		<p>obj.a: <input type="text"
				   v-model="obj.a"></p>
	</div>
</template>

<script type="text/ecmascript-6">
export default {
	name: "",
	data() {
		return {
			obj: {
				a: 123
			}
		}
	},
	watch: {
		'obj.a  ': { // 字符串形式监听
			handler(newVal, oldVal) {
				console.log('obj.a changed');
			},
			// deep: true
		}
	}
}
</script>

vue3.x中:

<script>
import { reactive, watch, watchEffect } from 'vue'
export default {
	setup () {
	
		const obj = reactive({a: 123})
	
		watch(() => obj, (newVal, oldVal) => {
			console.log(newVal, oldVal); // newVal、oldVal具有响应式
		}, { 
			deep: true, // 深度监听
			immediate: true, // 立即监听
		})


		// watchEffect自动收集依赖,不需要传递监听的内容
		const stop = watchEffect(() => {
			console.log(obj.a);
		})
		// 3秒后停止监听
		setTimeout(()=>{  
			stop();   
		},3000)
		
		return { obj }
	}
}
</script>

注意: 不要在 computed watch 中修改被依赖(或者被监听)的值,这样可能会导致无限循环

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫老板的豆

你的鼓励将是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值