watch监听在vue2和vue3中的用法详解(全)
首先写一个vue页面
<template>
<div>
<h1>监听一个属性</h1>
<p>求和:{{ sum }}</p>
<button @click="sum++">点我加1</button><br />
<h2>监听多个属性</h2>
<p>{{ tipsmessage }}</p>
<button @click="tipsmessage += 1">点我拼接1</button><br />
<h1>监听对象</h1>
<p>姓名:{{ obj.name }}</p>
<p>年龄:{{ obj.age }}</p>
<button @click="obj.age++">点我加年龄</button><br />
<h1>监听对象某一个属性变化</h1>
<p>薪资:{{ obj.test.salary }}</p>
<p>工作年限:{{ obj.test.year }}</p>
<button @click="obj.test.salary += 1000">点我涨薪</button>
<button @click="obj.test.year++">点我添加工作年限</button>
</div>
</template>
Vue2中的watch用法
<script>
data () {
return {
sum: 12,
tipsmessage: 'hell0',
obj: {
name: '隔壁老王',
age: '30',
test: {
salary: 3000,
year: 1
}
}
}
},
// 方式一:监听data中某个属性值的变化, 如果想要监听多个属性值的变化,可以继续往里面写
watch: {
sum(newVal, oldVal){
console.log('新值:', newVal)
console.log('旧值:', oldVal)
},
tipsmessage (newVal, oldVal) {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
}
}
// 方式二:监听data中obj对象的变化
// 这种监听整个对象变化的,需要加上deep,不然监听不到;不能监听到对象下的某个属性值的变化,监听不到具体的值变化,新值和旧值都一样
watch: {
obj: {
handler(newVal, oldVal) {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
},
deep: true
}
}
// 如果想要监听具体的属性变化,比如 name 、age变化时,才执行handler函数,则有两种方法:需要利用计算属性computed做中间层或者用引号将属性包裹起来
// 方式三: 监听data中obj对象下的某个具体属性的变化 ---- 第一种方法,使用computed做中间层
computed: {
getValue() {
return this.obj.age
}
},
watch: {
getValule(newVal, oldVal) {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
}
// 另一种写法
getValue: {
handler(newVal, oldVal) {
console.log('新值:', newVal)
console.log('旧值
:', oldVal)
}
}
}
// 方式四:监听data中obj对象下的某个具体属性的变化 ---- 第二种方法,使用引号包裹起来
watch: {
'obj.age'(newVal, oldVal) {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
}
// 还有另一种写法
'obj.age': {
handler(newVal, oldVal) {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
}
}
}
// 方式五:监听data中obj对象中的test对象 --- 暂时没什么好办法
// 方式六: 监听data中obj对象中的test对象中的具体属性值 ---- 还是两种方法
// 方法一:使用计算属性computed做中间层
computed: {
getValue() {
return this.obj.test.year
}
}
watch: {
getValue(newValue, oldValue) {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
}
// 另一种写法
getValue: {
handler (newVal, oldVal){
console.log('新值:', newVal)
console.log('旧值:', oldVal)
}
}
}
// 方法二:直接使用watch监听,用括号括起来
watch: {
'obj.test.year'(newVal, oldVal) {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
}
// 另一种写法
'obj.test.year': {
handler(newVal, oldVal) {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
}
}
}
</script>
总结:
1、vue2中监听data中的字段属性,直接采用 watch: { 字段名(newVal, oldVal) {语句}}就可以监听到该字段的变化
2、对于监听data中的对象及其属性的变化:
(1)监听整个对象: 采用watch: {obj: {handler(newVal,oldVal){语句}, deep: true}}方式,注意,该方法只能监听到整个对象的变化,不能监听到对象下的某个属性值的具体变化。即当该对象下的某个属性值发生变化时,使用这种方法监听,会执行handler函数,但获取到的数据 新值和旧值是一样的(都是新值),不能监听到其中的变化
(2)监听对象下的某一个属性,有两种方法:
1、使用计算属性computed做中间层,在使用watch监听
2、对象的具体属性可以直接用引号把属性括起来,然后使用 watch
3.监听data中的对象中的对象以及对象中的对象下的某个属性
(1)对于对象中的对象目前来说,我是没有什么好的办法的 — 不过使用$set应该可以解决
(2)监听对象中的对象下的某个属性,也有两种方法
1、使用计算属性computed做中间层,再使用watch监听 eg: computed: { getValue() { return this.obj.test.year}} watch: {getValue(newVal, oldVal) {语句}}
2、对象中的对象的某个具体属性值直接使用引号括起来,然后使用watch eg: watch: {‘obj.test.year’(newVal,oldVal){语句}}
Vue3中的watch用法
<script>
setup() {
let sum = ref(122)
let tipsmessage = ref('hello')
const obj = reactive({
name: '隔壁老王',
age: '30',
test: {
salary: 3000,
year: 1
}
})
// 方式一:监听单个基本数据类型(ref)
watch( sum, ( newVal, oldVal ) => {
console.log(newVal, oldVal)
})
// 方式二:监听多个基本数据类型(ref)
watch( [ sum, tipsmessage ], ( newVal, oldVal ) => {
// [ 122, 'hello1'] 监听出来结果发现新的值和旧的值都是数组
console.log( newVal, oldVal )
})
// 方式三:监听对象(reactive)
/*
vue3当前存在的问题:
1.reactive和ref响应式使用proxy代理无法正确监听并获取对象旧的值
2.强制开启深度监听,关闭无效(deep配置无效)
*/
watch(obj, (newVal, oldVal) => {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
})
// 这种方法不能监听到具体某个属性值的变化,只能监听到整体obj的变化,deep配置无效
// 方式四:监听对象下的某一个属性值 --- 这种可以监听到具体的属性值的变化
watch(()=>obj.age, ( newVal, oldVal) => {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
})
// 方式五:监听对象下的多个属性值变化
watch([() => obj.name, () => obj.age], (newVal, oldVal) => {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
// 这个打印出来的也是数组形式
})
// 方式六:监听对象下的整个对象的变化 --- 要加上deep,这种写法只能监听到整个对象的变化,不能获取到对象里的对象下的某个具体的属性值的变化,即打印出来的新值和旧值都一样
watch(() => obj.test, (newVal, oldVal) => {
console.log('新值2', newVal)
console.log('旧值', oldVal)
}, { deep: true })
// 另一种写法
watch(obj.test, (newVal, oldVal) => {
console.log('新值1', newVal)
console.log('旧值', oldVal)
}, { deep: true })
// 方式七: 监听对象下的对象内的具体属性值的变化
watch(() => obj.test.year, (newVal, oldVal) => {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
})
// 方式八:监听对象下的对象下的多个属性值变化
watch([()=>obj.test.year, ()=> obj.test.salary], (newVal, oldVal) => {
console.log('新值:', newVal)
console.log('旧值:', oldVal)
})
return {
sum,
tipsmessage,
obj
}
}
</script>
总结:
1、对于ref类型的数据进行监听,不能使用 ()=>字段名,的方法,而是采用直接写值进行监听,案例见方式一和方式二
2、对于reactive类型的数据进行监听,不要使用直接写属性名的方式监听:watch(属性名,(newVal, oldVal)=>{}),因为这种方式虽说可以执行函数,但却监听不到具体属性值的变化,打印出来的新值和旧值都一样。要使用watch(()=> 属性名, (newVal, oldVal)=>{})的方式,这样可以正确获取到值的变化