监视属性
作用
监视数据的变化, 与 Vue2 watch 作用一致
特点
Vue3
中的watch
只能监视以下四种数据:
ref
定义的数据reactive
定义的数据- 函数(
getter
函数)返回一个值 - 一个包含上述内容的数组
使用
在Vue3
中使用watch
的时候, 通常会遇到以下几种情况
情况一
监视ref
定义的基本类型数据: 直接写数据名即可, 监视的是其value
值的改变
- 代码示例
vue
<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>
情况二
监视ref
定义的对象类型数据: 直接写数据名, 监视的是对象的地址值, 若想监视对象内部的数据, 要手动开启深度监视
注意
- 若修改的是
ref
定义的对象中的属性,newValue
和oldValue
都是新值, 因为它们是同一个对象 - 若修改整个
ref
定义的对象,newValue
是新值,oldValue
是旧值, 因为不是同一个对象了
- 代码示例
vue
<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>
情况三
监视reactive
定义的对象类型数据, 且默认开启了深度监视
- 代码示例
vue
<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="changeTest">修改测试</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 changeTest() {
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>
情况四
监视ref
或reactive
定义的对象类型数据中的某个属性
注意
- 若该属性值不是对象类型, 需要写成函数形式
- 若该属性值是对象类型, 可直接写, 也可写成函数, 推荐写成函数
结论: 监视的要是对象里的属性, 那么最好写函数式
若是对象监视的是地址值, 需要关注对象内部, 需要手动开启深度监视
vue
<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>
情况五
监视上述的多个数据
vue
<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>