<template> <divclass="watchDemo"> <h1>D:侦听响应式对象的属性</h1> 车队长姓名:{{ vehicleGroup.leaderName }} <ul> <li>车辆A:{{ vehicleGroup.vehicleA.driverName }},{{ vehicleGroup.vehicleA.carPlateNo }}</li> <li>车辆B:{{ vehicleGroup.vehicleB.driverName }},{{ vehicleGroup.vehicleB.carPlateNo }}</li> </ul> <button @click="changeLeader">修改车队长</button> <button @click="changeVehicleA">修改车A</button> <button @click="changeVehicleB">修改车B</button> <button @click="changeAllVehicle">修改车队</button> </div> </template> <script lang='ts' setupname='WatchDemo'> import{ reactive,watch } from 'vue' let vehicleGroup = reactive({ leaderName:"车队长A", vehicleA: { driverName:"车A司机", carPlateNo:"车A车牌号" }, vehicleB: { driverName:"车B司机", carPlateNo:"车B车牌号" } }) function changeLeader() { vehicleGroup.leaderName = vehicleGroup.leaderName + "+" } function changeVehicleA() { vehicleGroup.vehicleA.carPlateNo = vehicleGroup.vehicleA.carPlateNo + "-" vehicleGroup.vehicleA.driverName = vehicleGroup.vehicleA.driverName + "-" } function changeVehicleB() { vehicleGroup.vehicleB.carPlateNo="车B车牌号~~new" vehicleGroup.vehicleB.driverName="车B司机~~~~new" } function changeAllVehicle() { vehicleGroup.vehicleA= { driverName:"张师傅", carPlateNo:"经A88888" } vehicleGroup.vehicleB= { driverName:"李师傅", carPlateNo:"齐C66666" } } //侦听对象的基本类型 // watch(getLeaderName, (newVal, oldVal) => { // console.log('车队长变了:', newVal, oldVal); // }) // function getLeaderName(){ // return vehicleGroup.leaderName // } // 简单写法 watch(() =>vehicleGroup.leaderName,(newVal, oldVal) =>{ console.log('车队长变了:', newVal, oldVal); }) // 侦听对象的对象 // 写法1,侦听属性对象。changeVehicleA可以侦听,changeAllVehicle无法侦听 // watch(vehicleGroup.vehicleA,(newVal,oldVal)=>{ // console.log('车A变了:', newVal, oldVal); // }) // 写法2,侦听属性对象的getter函数。changeVehicleA无法侦听,changeAllVehicle可以侦听 // watch(()=>vehicleGroup.vehicleA,(newVal,oldVal)=>{ // console.log('车A变了:', newVal, oldVal); // }) // 写法3,侦听属性对象的getter函数,并开启深度侦听。changeVehicleA、changeAllVehicle都可以侦听 watch(() =>vehicleGroup.vehicleA,(newVal, oldVal) =>{ console.log('车A变了:', newVal, oldVal); }, {deep:true}) </script> <style> .watchDemo{ background-color: darkkhaki; } </style>
如果侦听的属性是基本类型,按照 简单写法 即可。
如果侦听的属性是对象,按照 写法3,无论是修改对象的内部属性,还是修改整个对象,都能触发侦听。
watch数组&watchEffect
前文介绍的都是watch一个数据源,在实际的开发中,我们一般是侦听多个数据源,综合考虑进行逻辑处理,其方法如下:
<template> <div class="watchEffectDemo"> <h1>Watch数组</h1> 姓名:<input type="text" v-model="jobSeeker.userName" required> 年龄:<select v-model="jobSeeker.age" required> <option v-bind:value="0">请选择</option> <option v-bind:value="34">34岁</option> <option v-bind:value="35">35岁</option> <option v-bind:value="36">36岁</option> </select> 学历:<select v-model="jobSeeker.eduBg"> <option v-for="option in eduBgs" v-bind:value="option.value" required> {{ option.text }} </option> </select> </div> </template> <script lang='ts' setup name='WatchEffectDemo'> import { reactive, watch } from 'vue' let eduBgs = [ { value: 0, text: "请选择" }, { value: 1, text: "博士" }, { value: 2, text: "硕士" }, { value: 3, text: "本科" }, { value: 99, text: "大专" } ] let jobSeeker = reactive({ userName: "", eduBg: 0, age: 0 }) watch([() => jobSeeker.age, () => jobSeeker.eduBg], (newVal) => { let [age, eduBg] = newVal if (age === 0 || eduBg === 0) { return } if (age < 35 && eduBg < 99) { console.log('发送请求:', jobSeeker); alert("真的已提交") } else { console.log('并没有提交', jobSeeker); alert("已提交") } }) </script> <style> .watchEffectDemo { background-color: lavender; } </style>
与watch基本一致,只是数据源那里,变成了数组。
回调函数3个参数【新值、旧值、副作用清理回调函数】,后两个本节不需要,就没写。
与watch一个数据源一样,该注意的,watch多个数据源也一样注意,本节不赘述。
这样固然解决了watch多个数据源的需求,但在实际工作,watch的可能有N个数据源,全写在数组就很繁冗了,这就引入了watchEffect。
另外,在新版本的Vue中(我的是3.5.13),如果用watch侦听数组,控制台会提示:
watch(fn, options?)` signature has been moved to a separate API. Use `watchEffect(fn, options?)` instead. `watch` now only supports `watch(source, cb, options?) signature.
官方建议使用watchEffect来侦听多个数据源,改造如下:
watchEffect(() => { if (jobSeeker.age === 0 || jobSeeker.eduBg === 0) { return } if (jobSeeker.age < 35 && jobSeeker.eduBg < 99) { console.log('发送请求:', jobSeeker); alert("真的已提交") } else { console.log('并没有提交', jobSeeker); alert("已提交") } })
watchEffect不用像watch那样,指定要侦听的数据源,它会自动跟踪回调的响应式依赖。
watchEffect会立即执行一次回调函数,类似watch里的{immediate:true}。
watchEffect拿不到原值。