说明
watch可以用来监听一个响应式变量发生的变化,它和computed很相识,它们都是用来监听响应式变量发生的变化对其进行一些处理。
watch和computed不同点
1.computed要求返回一个值,watch不要求返回值。
2.computed是通过监听响应式变量会对其进行计算等到一个新的值,一般用于计算价格,排序,过滤数据等操作,watch是对响应式变量的改变而进行一些更加复杂的逻辑处理或异步操作,如:异步请求。
watch语法
import {ref, watch} from "vue";
const name=ref("");
watch(name,(newName,oldName)=>{
//逻辑处理
//异步操作
})
watch组成
name:监听的数据源类型,可以是一个响应式变量、对象、数组,或者是一个getter函数
newName:监听到的响应式变量的变化
oldName:变化前的响应式变量
基本使用
监听单个响应式变量
<template>
<input type="text" v-model="name">
</template>
<script setup>
import {ref,watch} from "vue";
const name=ref("")
watch(name,(newName,oldName)=>{
console.log("新值:"+newName);
console.log("旧值:"+oldName);
})
</script>
运行结果:
这里一运行的时候name是空的所以第一改变name的值时,旧值为空,第二次改变的时候就可以显而易见的看出旧值时第一次的值“1”
监听对象属性
错误使用
const person=ref({
name:'张三',
age:18
});
watch(person.name,(newName,oldName)=>{
console.log(newName);
console.log(oldName);
})
正确使用
使用我们的getter函数来监听对象的属性
import {ref, watch} from "vue";
const person=ref({
name:'张三',
age:18
});
watch(()=>person.value.name,(newName,oldName)=>{
console.log(newName);
console.log(oldName);
})
因为person是ref对象,所以要用person.value.name来监听
深层监听
当我们要监听一个对象的使用直接在第一个属性位置写上对象名是不会进行监听的,默认情况下,watch是浅层监听,这个使用我们就要开启深层监听来监听对象所发生的变化,两种办法:
1.把我们的ref改成reactive
import {ref,watch,reactive} from "vue";
const person=reactive({
name:'张三',
age:18
});
watch(person,(newName,oldName)=>{
console.log(newName);
console.log(oldName);
})
原因:因为ref本来是用来创建响应式变量的,reactive是创建响应式对象的,这里用来ref创建响应式对象其实是不对的,用它的原因是ref比reactive的内存的占用和性能开销更低,如果在这个对象不考虑会被watch监听的情况下可以用ref,如果要被watch监听就需要使用reactive,所以把用reactive创建的对象watch会隐式的为它创建一个深层监听。
2.使用deep选项强制转换成深层监听
import {ref,watch,reactive} from "vue";
const person=ref({
name:'张三',
age:18
});
watch(person,(newName,oldName)=>{
console.log(newName);
console.log(oldName);
},{deep:true})
即时回调
在我们可能在某些时候在监听器一创建的时候就强制要求监听器进行一次回调,这时我们就可以用即时回调选项了
<template>
<input type="text" v-model="name">
</template>
<script setup>
import {ref,watch} from "vue";
const name=ref("张三")
watch(name,(newName,oldName)=>{
console.log("新值:"+newName);
console.log("旧值:"+oldName);
},{immediate:true})
</script>
旧值是undefined的原因是,我们给了name默认值,但是由于用了即时回调选项,在监听器一创建的时候要求了进行一次回调,本属于旧值的name由于进行了一次回调就成了新值,那么旧值就会变成undefined,旧值是undefined是因为默认的name值成了新值后没有之前的状态可以比较,所以旧值就是undefined。
watchEffect
它不用指定监听的响应式变量,因为它是监听所有有改变的响应式变量、对象、数组,只要有改变就会被他捕捉监听,占用的内存以及性能可想而知,并且它是一创建后就会进行回调。
使用方法
<template>
<input type="text" v-model="name">
</template>
<script setup>
import {ref,watchEffect} from "vue";
const name=ref("张三")
watchEffect(()=>{
console.log(name.value);
})
</script>