【vue】vue2和vue3 watch监听(监听多个数据;监听对象属性变化,新旧值相同;等情况处理)

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)=>{})的方式,这样可以正确获取到值的变化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值