作用:监听数据的变化(和Vue2中的watch作用一致)
特点:Vue3中的watch只能监听以下四种数据
1. ref 定义的数据
2. reactive 定义的数据
3. 函数返回的一个值
4. 一个包含上述内容的数组
情况一:监视【ref】定义的【基本类型】数据
watch接收两个参数
第一个:要监听的值
第二个:函数,接收两个参数:新的值与旧的值
watch返回一个函数,函数作用是停止监听
<script setup lang="ts"> import { ref,watch } from 'vue' let sum = ref(1); let changeSun = ()=>{ sum.value++; } // watch 接收两个参数 // 第一个是要监听的值 // 第二个是监听的值发现变化要执行的函数 // watch 返回一个函数,函数作用是停止监听 const stopWatch = watch(sum, (newValue,oldValue)=>{ // newValue 是新的值 // oldValue 是旧的值 if(newValue>=10){ stopWatch() } }) </script>
复制
情况二:监视【ref】定义的【对象类型】数据
当监视【ref】定义的【对象类型】数据时:
1. 修改对象里的某个属性时是不会触发监听的
2. 只有修改整个对象的时候才会触发
如果要修改对象里的某个属性时也触发监听侧需要传递第三个参数
<script setup lang="ts"> import { ref, watch } from 'vue' let person = ref({ name: "张三", age: 18 }); // 监听 person const stopWatch = watch(person, (newValue, oldValue) => { console.log(newValue, oldValue) }) // 修改name不会触发监听 let changeName = () => { person.value.name += "-" } // 修改整个对象才会触发监听 let changePerson = () => { person.value = { name: "李四", age: 19 }; } </script> <template> 姓名:{{ person.name }} 年龄:{{ person.age }} <button @click="changeName">修改姓名</button> <button @click="changePerson">都改</button> </template>
复制
如果要修改对象里的某个属性时也触发监听侧需要传递第三个参数
第三个参数是一个配置对象:{deep: true}可选值:
1. immediate:在监听创建时立即触发回调,第一次调用时旧值是undefined
2. deep:如果监听的值是对象,强制使用深度遍历,一遍在深层级变更时触发回调
3. flush:调整回调函数的刷新时机
'pre' :在组件更新更新前运行,默认为'pre'
'post':在组件更新更新后运行
'sync':强制效果始终同步触发。然而,这是低效的,应该很少需要。
4. onTrack / onTrigger:调试监听的依赖
onTrack(e) {
// 当监听的值被追踪为依赖时触发
debugger
},
onTrigger(e) {
// 当监听的值被更改时触发
debugger
}
注意:只修改对象中的某个属性时新值与旧值是一样的,只有修改整个对象时新值与旧值才正确
<script setup lang="ts"> import { ref, watch } from 'vue' let person = ref({ name: "张三", age: 18 }); const stopWatch = watch(person, (newValue, oldValue) => { console.log(newValue, oldValue) },{deep: true}) // 加上{deep: true}则修改person中的name属性也会触发监听 let changeName = () => { person.value.name += "-" } let changePerson = () => { person.value = { name: "李四", age: 19 }; } </script> <template> 姓名:{{ person.name }} 年龄:{{ person.age }} <button @click="changeName">修改姓名</button> <button @click="changePerson">都改</button> </template>
复制
情况三:监视【reactive】定义的【对象类型】数据
1. 监听时默认开启了深度监视,并且关不掉
2. 只修改对象中的某个属性时新值与旧值是一样的,只有修改整个对象时新值与旧值才正确
<script setup lang="ts"> import { reactive, watch } from 'vue' let person = reactive({ name: "张三", age: 18 }); // 能监听到 let btn1 = () => { person.name += "-" } // 能监听到 let btn2 = () => { Object.assign(person, { name: "李四", age: 19 }); } // 监听不到 let btn3 = () => { person = { name: "李四", age: 19 }; } // 默认开启深度监视 const stopWatch = watch(person, (newValue, oldValue) => { console.log(newValue, oldValue) })
复制
情况四:监视【ref、reactive】定义的【对象类型】数据中的某个属性
1. 监听的属性是基本数据类型,则需要写成函数返回值
<script setup lang="ts"> import { reactive, watch } from 'vue' let person = reactive({ name: "张三", age: 18 }); // 能触发监听 let btn1 = () => { person.name += "-" } // 不能触发监听 let btn2 = () => { person.age++ } // 监听的值写成函数返回值,只能监听到 name 的改变 watch(()=>person.name, (newValue, oldValue) => { console.log(newValue, oldValue) }) </script>
复制
2. 监听的属性是一个对象,则可以直接写或者写成函数返回值
<script setup lang="ts"> import { reactive, watch } from 'vue' let person = reactive({ cra:{ c1:"奔驰", c2:"宝马" } }); // 只能监听到 c1、c2的变化,整个 cra 对象改变监听不到 watch(person.cra, (newValue, oldValue) => { console.log("直接写") }) // 只能监听到整个 cra 对象改变,c1、c2的变化监听不到 watch(()=>person.cra, (newValue, oldValue) => { console.log("函数形式") }) // cra、c1、c2 都能监听到,推荐写法 watch(()=>person.cra, (newValue, oldValue) => { console.log("函数形式+深度监听") },{deep:true}) </script>
复制
情况五:监视上述多个数据
<script setup lang="ts"> import { reactive, watch } from 'vue' let person = reactive({ name: "张三", age: 18, cra: { c1: "奔驰", c2: "宝马" } }); // 监视上述多个数据 watch([()=>person.name,person.cra], (newValue,oldValue) => { console.log("监视上述多个数据",newValue,oldValue) }) // 可以监听到 let btn1 = () => { person.name += "-" } // 可以监听到 let btn2 = () => { person.cra.c1 ="宝马123" } // 不可以监听到,要是不明白这里为什么可以监听到在回去看看情况四 let btn3 = () => { person.cra = { c1: "奔驰123", c2: "宝马123" } } </script>
复制
- 平时开发中常用的是情况一与情况四,记牢这两个写法即可