Vue 2x 系列之(九)监视和侦听属性

监视/侦听属性【watch】

用于监视某一个属性的变化

监视属性watch:
	1.当被监视的属性变化时, 回调函数【handler()】自动调用, 进行相关操作
	2.监视的属性必须存在,才能进行监视!!【监视不存在的属性不会报错】
	3.配置监视的两种写法:
			(1).new Vue时传入watch配置
			(2).通过vm.$watch监视

watch中的配置项:

配置项名称 含义
immediate true/false 初始化时让handler调用一下
handler function(){} 当监视的属性发生改变时要调用的函数
deep true/false 是否开启深度监视,见“九、1.深度监视”
<body>
	<div id="root">
		<h2>今天天气很{{info}}</h2>
		<button type="button" @click="switchWeather">切换天气</button>
	</div>
	<script type="text/javascript">
		//阻止 vue 在启动时生成生产提示。
		Vue.config.productionTip = false	
		
		const vm = new Vue({
			el: "#root",
			data:{
				isHot: true
			},
			computed:{
				info(){
					return this.isHot ? '炎热' : '凉爽'
				}
			},
			methods:{
				switchWeather(){
					this.isHot =  !this.isHot
				}
			},
			// 配置监视的第一种方式
			// watch:{
			// 	isHot:{
			// 		immediate:true, //初始化时让handler调用一下
          	 //		 //handler方法被调用时,会将newValue(变化之后的值), oldValue(变化之前的值)两
          	 //		 //个参数传给handler方法,我们可以拿来用
			// 		handler(newValue,oldValue){
			// 			console.log('isHot变了',newValue,oldValue)
			// 		}
			// 	}
			// }
		});
		// 配置监视的第二种方式
		// 第一个参数一定要传入字符串
      	 // watch可以监视data中的属性,也可以监视计算属性
      	 // 配置对象{}中的key原始写法是'info',可以简写为info。这里的'info'并不在配置对象中,所以不能
         // 简写,这里如果直接写info,就会去查找info变量了,而我们的本意是传一个字符串
		vm.$watch('info',{
			immediate:true, //初始化时让handler调用一下
			handler(newValue,oldValue){
				console.log('info变了',newValue,oldValue)
			}
		})
	</script>
</body>

1. 深度监视

深度监视:
		(1).Vue中的watch默认不监测data中对象内部值的改变(一层)。
		(2).配置deep:true可以监测对象内部值改变(多层)。
备注:
		(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以【为了存在多级结构时不影响效率】!
		(2).使用watch时根据数据的具体结构,决定是否采用深度监视。
<body>
	<!-- 准备好一个容器-->
	<div id="root">
		<h2>今天天气很{{info}}</h2>
		<button @click="changeWeather">切换天气</button>
		a的值是{{numbers.a}}
		<button @click="numbers.a++">点我</button>
		<button @click="numbers = {a:666,b:888}">点我</button>
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
	
	const vm = new Vue({
		el:'#root',
		data:{
			isHot:true,
			numbers: {
				a: 1,
				b: 1
			}
		},
		computed:{
			info(){
				return this.isHot ? '炎热' : '凉爽'
			}
		},
		methods: {
			changeWeather(){
				this.isHot = !this.isHot
			}
		},
		watch:{
			//监视多级结构中某个属性的变化【多级结构中某个属性的变化会触发handler方法的调用】
			'numbers.a':{
				// immediate:true, //初始化时让handler调用一下
				//handler什么时候调用?当isHot发生改变时。
				handler(newValue,oldValue){
					console.log('numbers.a',newValue,oldValue)
				}
			},
			// 监视多级结构中任意属性的变化【多级结构中任意一个属性的变化都会触发handler方法的调用】
			numbers:{
				deep: true,
				handler(){
					console.log('numbers改变了')
				}
			}
		}
	})

</script>

2. 监视的简写形式

前提:配置项仅有handler时就可以开启监视的简写形式

如何简写

//这里给出了两种配置监视方式的简写形式
watch:{
	//正常写法
	/* isHot:{
		// immediate:true, //初始化时让handler调用一下
		// deep:true,//深度监视
		handler(newValue,oldValue){
			console.log('isHot被修改了',newValue,oldValue)
		}
	}, */
	//简写
	/* isHot(newValue,oldValue){
		console.log('isHot被修改了',newValue,oldValue,this)
	} */
}

//正常写法
/* vm.$watch('isHot',{
immediate:true, //初始化时让handler调用一下
deep:true,//深度监视
handler(newValue,oldValue){
	console.log('isHot被修改了',newValue,oldValue)
}
}) */

//简写
//注:这里的function也属于Vue管理的函数,不能写成箭头函数的形式,否则this的指向也会有问题
vm.$watch('isHot',function(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
})

3. 计算属性VS监视属性

监视属性:可以开启异步任务

<body>
	<!-- 准备好一个容器-->
	<div id="root">
		姓:<input type="text" v-model="firstName"> <br/><br/>
		名:<input type="text" v-model="lastName"> <br/><br/>
		全名:<span>{{fullName}}</span> <br/><br/>
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el:'#root',
		data:{
			firstName:'张',
			lastName:'三',
			fullName: '张-三'
		},
		watch: {
			firstName(newValue){
				// 这里的定时器确实是在Vue管理的函数【firstName】中开启的,但定时器所指定的回调函数【箭头函数】是不受Vue控制的,是由浏览器定时器管理模块控制的,回调函数也是由js引擎调用的
				setTimeout(()=>{
					// 这里的定时器回调函数如果写为箭头函数,由于箭头函数是没有this的,就会往外找,也就找到了firstName这个函数,最后输出的this就是firstName的this,也就是Vue实例;
					// 这里的定时器回调函数如果写为普通函数,那么this就是Window实例
					console.log(this)
					this.fullName = newValue + '-' + this.lastName
				}, 1000)
			},
			lastName(newValue){
				this.fullName = this.firstName + '-' + newValue
			}
		}
	})
</script>

计算属性:不能开启异步任务去维护数据

<body>
	<!-- 准备好一个容器-->
	<div id="root">
		姓:<input type="text" v-model="firstName"> <br/><br/>
		名:<input type="text" v-model="lastName"> <br/><br/>
		全名:<span>{{fullName}}</span> <br/><br/>
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el:'#root',
		data:{
			firstName:'张',
			lastName:'三',
		},
		computed:{
			fullName(){
				console.log('get被调用了')
              	 // setTimeout:单位是毫秒
				setTimeout(()=>{
					// 这里的return并不是fullName的返回值,而是箭头函数的返回值
					// 也就是说,这样写fullName函数的返回值是undefined,因此取不到fullName的值
					return this.firstName + '-' + this.lastName
				}, 1000)
			}
		}
	})
</script>

各自的应用场景:

  • 当同一个功能计算属性和监视属性都能实现时优先使用计算属性
  • 当需要进行异步计算时只能使用监视属性【这是因为监视属性并不是依靠返回值给监视的属性赋值的,而计算属性是完全依靠返回值进行赋值的】

watch:命令式

computed和watch之间的区别:
		1.computed能完成的功能,watch都可以完成。
		2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
两个重要的小原则:【总之,我们的目的就是让函数内部的this指向Vue的实例,这样以后在我们需要使用Vue实例身上的东西时,我们能够通过this进行调用】
			1.所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
			2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。
posted @   刘二水  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示