上一章,我们主要介绍了计算属性与方法的区别、及计算属性Vue2和Vue3对比;
前言:这章主要介绍,vue中watch概念及vue2、3版本使用区别;
watch概念:允许你在数据变化时执行特定的逻辑(方法),从而实现更复杂的数据处理和业务逻辑。
第一:Vue2中的使用~监听器(监听基本类型、引用数据类型、立即执行):
- 1.在 Vue 实例中,你可以定义一个 watch 属性来监听 data 属性的变化。【基本数据类型】
new Vue({
el: '#app',
data: {
message: 'Hello'
},
watch: {
message(newVal, oldVal) {
console.log(`消息发生变化 ${oldVal} 和 ${newVal}`);
}
}
});
- 2当你想监听一个对象或数组的内部变化时,你可以使用 deep 选项。【引用数据类型】
new Vue({
el: '#app',
data: {
obj: { a: 1 }
},
watch: {
obj: {
handler(newVal, oldVal) {
console.log('obj changed');
},
deep: true
}
}
});
3.使用 immediate 选项,监听器将在 Vue 实例创建时立即执行一次。【立刻执行】
new Vue({
el: '#app',
data: {
message: 'Hello'
},
watch: {
message: {
handler(newVal, oldVal) {
console.log(`消息发生变化 ${oldVal}和 ${newVal}`);
},
immediate: true
}
}
});
第二:vue3中的使用(以setup语法糖里举例):
vue3官网提到一共四种监听使用(有分的细-5种)
- 1.监听~ ref 定义的【基本类型】
<template>
<div class="person">
<h1>情况一:监视【ref】定义的【基本类型】数据</h1>
<h2>当前求和为:{{sum}}</h2>
<button @click="changeSum">点我sum+1</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {ref,watch} from 'vue'
// 数据
let sum = ref(0)
// 方法
function changeSum(){
sum.value += 1
}
// 监视,情况一:监视【ref】定义的【基本类型】数据
const stopWatch = watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)
if(newValue >= 10){
stopWatch()
}
})
</script>
- 2.深度监听~ ref 定义的【引用数据类型】
<template>
<div class="person">
<h1>情况二:监视【ref】定义的【对象类型】数据</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePerson">修改整个人</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {ref,watch} from 'vue'
// 数据
let person = ref({
name:'张三',
age:18
})
// 方法
function changeName(){
person.value.name += '~'
}
function changeAge(){
person.value.age += 1
}
function changePerson(){
person.value = {name:'李四',age:90}
}
/*
监视,情况一:监视【ref】定义的【对象类型】数据,监视的是对象的地址值,若想监视对象内部属性的变化,需要手动开启深度监视
watch的第一个参数是:被监视的数据
watch的第二个参数是:监视的回调
watch的第三个参数是:配置对象(deep、immediate等等.....)
*/
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{deep:true})
</script>
注意:
*若修改的是ref定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。
*若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。
- 3.深度监听~ reactive定义的【引用数据类型】
与 Vue 2 不同,Vue 3 的 watch 函数没有内置的 immediate 选项。但是,你可以在 watch 函数中立即调用回调函数来实现类似的效果。
<template>
<div class="person">
<h1>情况三:监视【reactive】定义的【对象类型】数据</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePerson">修改整个人</button>
<hr>
<h2>测试:{{obj.a.b.c}}</h2>
<button @click="test">修改obj.a.b.c</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {reactive,watch} from 'vue'
// 数据
let person = reactive({
name:'张三',
age:18
})
let obj = reactive({
a:{
b:{
c:666
}
}
})
// 方法
function changeName(){
person.name += '~'
}
function changeAge(){
person.age += 1
}
function changePerson(){
Object.assign(person,{name:'李四',age:80})
}
function test(){
obj.a.b.c = 888
}
// 监视,情况三:监视【reactive】定义的【对象类型】数据,且默认是开启深度监视的
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
})
watch(obj,(newValue,oldValue)=>{
console.log('Obj变化了',newValue,oldValue)
})
</script>
4.监视ref或reactive定义的【对象类型】数据中的某个属性,
注意点如下:
*若该属性值不是【对象类型】,需要写成函数形式。
*若该属性值是依然是【对象类型】,可直接编,也可写成函数,建议写成函数。
<template>
<div class="person">
<h1>情况四:监视【ref】或【reactive】定义的【对象类型】数据中的某个属性</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeC1">修改第一台车</button>
<button @click="changeC2">修改第二台车</button>
<button @click="changeCar">修改整个车</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {reactive,watch} from 'vue'
// 数据
let person = reactive({
name:'张三',
age:18,
car:{
c1:'奔驰',
c2:'宝马'
}
})
// 方法
function changeName(){
person.name += '~'
}
function changeAge(){
person.age += 1
}
function changeC1(){
person.car.c1 = '奥迪'
}
function changeC2(){
person.car.c2 = '大众'
}
function changeCar(){
person.car = {c1:'雅迪',c2:'爱玛'}
}
// 监视,情况四:监视响应式对象中的某个属性,且该属性是基本类型的,要写成函数式
/* watch(()=> person.name,(newValue,oldValue)=>{
console.log('person.name变化了',newValue,oldValue)
}) */
// 监视,情况四:监视响应式对象中的某个属性,且该属性是对象类型的,可以直接写,也能写函数,更推荐写函数
watch(()=>person.car,(newValue,oldValue)=>{
console.log('person.car变化了',newValue,oldValue)
},{deep:true})
</script>
结论:监视的要是对象里的属性,那么最好写函数式,注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视。
5.监听上述多个数据
<template>
<div class="person">
<h1>情况五:监视上述的多个数据</h1>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeC1">修改第一台车</button>
<button @click="changeC2">修改第二台车</button>
<button @click="changeCar">修改整个车</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {reactive,watch} from 'vue'
// 数据
let person = reactive({
name:'张三',
age:18,
car:{
c1:'奔驰',
c2:'宝马'
}
})
// 方法
function changeName(){
person.name += '~'
}
function changeAge(){
person.age += 1
}
function changeC1(){
person.car.c1 = '奥迪'
}
function changeC2(){
person.car.c2 = '大众'
}
function changeCar(){
person.car = {c1:'雅迪',c2:'爱玛'}
}
// 监视,情况五:监视上述的多个数据
watch([()=>person.name,person.car],(newValue,oldValue)=>{
console.log('person.car变化了',newValue,oldValue)
},{deep:true})
</script>
第三:计算属性与监听器区别
Vue中的监听器(watch)和计算属性(computed)在功能和使用上有一些区别。
-
1.功能上:
计算属性:主要用于处理复杂逻辑和计算,基于它们的依赖进行缓存。只有当依赖的值发生改变时,计算属性才会重新计算。
监听器:用于观察和响应 Vue 实例上的数据变化。当指定的数据项(如 data 或 computed 属性的值)发生变化时,监听器会触发相应的回调函数,执行特定的业务逻辑。 -
2.缓存机制:
计算属性:有缓存机制,只有当其依赖的属性发生变化时,才会重新计算。这有助于提高性能,特别是当计算属性涉及复杂的计算或异步操作时。
监听器:没有缓存机制,每次监听的数据发生变化时,都会执行回调函数。 -
3.异步操作:
计算属性:不支持异步操作。如果需要在计算属性中进行异步操作,通常需要使用方法来替代。
监听器:支持异步操作。你可以在监听器的回调函数中执行异步操作,如 API 调用等。 -
4.数据依赖:
计算属性:可以基于其他数据属性进行计算,并返回一个新的值。这个值会被缓存,并且只有当依赖的属性发生变化时才会重新计算。
监听器:通常用于监听单个数据属性的变化。虽然也可以监听多个属性,但这通常不是监听器的典型用法。 -
5.使用场景:
计算属性:当你需要根据其他属性进行计算,并得到一个新的值时,使用计算属性。例如,购物车商品结算总价等。
监听器:当你需要在数据变化时执行特定的逻辑,例如数据验证、异步获取数据等,使用监听器。例如,当搜索框内容发生变化时,发送请求获取相关搜索结果。