首页 > 编程笔记 > JavaScript笔记
阅读:242
Vue watch(监听器)用法详解
Vue 中的监听器是一个对象,以 key-value 的形式表示,key 是需要监听的表达式,value 是对应的回调函数,value 也可以是方法名,或者包含选项的对象。
Vue 实例将会在实例化时调用 $watch() 遍历 watch 对象的每一个 property。同时,当差值数据变化时,执行异步或开销较大的操作时,可以通过监听器的方式来达到目的。
监听器在 Vue 实例的 watch 选项中定义,它包括两个参数,第一个参数是监听数据的新值,第二个是旧值。
【实例一】监听 data() 函数中的 message 属性,并在控制台中打印新值和旧值。

图 1 监听属性值的变化
注意,不要用箭头函数来定义 watch 函数。例如:
【实例二】使用监听器方法。
在 Chrome 浏览器中运行程序,在第一个输入框中输入 6,可以发现第二个输入框的值相应地变为 60,如下图所示。

图 2 监听方法
同样,在第二个输入框中输入内容,第一个输入框也会相应地变化。
deep 属性在监听对象属性变化时使用,该选项的值为 true,表示无论该对象的属性在对象中的层级有多深,只要该属性的值发生变化,都会被监测到。
监听器函数在初始渲染时并不会被调用,只有在后续监听的属性发生变化时才会被调用;如果需要监听器函数在监听开始后立即执行,可以使用 immediate 选项将其值设置为 true。
【实例三】监听 goods 对象,在商品价格改变时显示是否可以采购。

图 3 输入“860”效果
从上面的示例可以发现,页面初始化时监听器不会被调用,只有在监听的属性发生变化时才会被调用;如果要让监听器函数在页面初始化时执行,可以使用 immediate 选项,将其值设置为 true。

图 4 immediate选项的作用
在上面的示例中,使用 deep 属性深入监听,监听器会一层一层地往下遍历,给对象的所有属性都加上这个监听器,修改对象里面任何一个属性都会触发监听器里的 handler 函数。
在实际开发过程中,用户很可能只需要监听对象中的某几个属性,设置 deep:true 之后就会增大程序性能的开销。这里可以直接监听想要监听的属性,例如修改上面的示例,只监听 score 属性。
【实例四】监听器对象的单个属性。

图 5 输入“北京”的效果
Vue 实例将会在实例化时调用 $watch() 遍历 watch 对象的每一个 property。同时,当差值数据变化时,执行异步或开销较大的操作时,可以通过监听器的方式来达到目的。
监听器在 Vue 实例的 watch 选项中定义,它包括两个参数,第一个参数是监听数据的新值,第二个是旧值。
【实例一】监听 data() 函数中的 message 属性,并在控制台中打印新值和旧值。
<div id="app">
时:<input type="text" v-model="time">
分钟:<input type="text" v-model="minute">
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
//创建一个应用程序实例
const vm= Vue.createApp({
//该函数返回数据对象
data(){
return{
time:0,
minute:0
}
},
watch:{
time(val) {
this.minute = val * 60;
},
// 监听器函数也可以接收两个参数,val是当前值,oldVal是改变之前的值
minute(val, oldVal) {
this.time = val / 60;
}
}
//在指定的DOM元素上装载应用程序实例的根组件
}).mount('#app');
</script>
在 Chrome 浏览器中运行程序,这里将分别监听数据属性 time 和 minute 的变化,当其中一个数据的值发生变化时,就会调用对应的监听器,经过计算得到另一个数据属性的值,结果如下图所示。
图 1 监听属性值的变化
注意,不要用箭头函数来定义 watch 函数。例如:
time:(val) =>{
this.time = val;
this.minute = this.time*60
}
因为箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.time 和 this.minute 都是 undefined。监听方法
在使用监听器的时候,除了直接写一个监听处理函数外,还可以接收一个加字符串形式的方法名,方法在 methods 选项中定义。【实例二】使用监听器方法。
<div id="app">
<p>元和角的转换</p>
<p>元:<input type="text" v-model="yuan"></p>
<p>角:<input type="text" v-model="jiao"></p>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
//创建一个应用程序实例
const vm= Vue.createApp({
//该函数返回数据对象
data(){
return{
yuan:0,
jiao:0
}
},
methods:{
method1:function (val,oldVal) {
this.jiao=val*10;
},
method2:function (val,oldVal) {
this.yuan=val/10;
}
},
watch:{
//监听yuan属性,yuan变化时,使jiao属性等于yuan*10
yuan:"method1",
//监听jiao属性,jiao变化时,使val属性等于jiao/10
jiao:"method2"
}
//在指定的DOM元素上装载应用程序实例的根组件
}).mount('#app');
</script>
示例中监听了 yuan 和 jiao 属性,后面直接加上字符串形式的方法名 method1 和 method2,最后在页面中使用 v-model 指令绑定 yuan 和 jiao 属性。在 Chrome 浏览器中运行程序,在第一个输入框中输入 6,可以发现第二个输入框的值相应地变为 60,如下图所示。

图 2 监听方法
同样,在第二个输入框中输入内容,第一个输入框也会相应地变化。
监听对象
当监听器监听一个对象时,使用 handler 定义数据变化时调用的监听器函数还可以设置 deep 和 immediate 属性。deep 属性在监听对象属性变化时使用,该选项的值为 true,表示无论该对象的属性在对象中的层级有多深,只要该属性的值发生变化,都会被监测到。
监听器函数在初始渲染时并不会被调用,只有在后续监听的属性发生变化时才会被调用;如果需要监听器函数在监听开始后立即执行,可以使用 immediate 选项将其值设置为 true。
【实例三】监听 goods 对象,在商品价格改变时显示是否可以采购。
<div id="app">
商品价格:<input type="text" v-model="goods.price">
<p>{{pess}}</p>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
//创建一个应用程序实例
const vm= Vue.createApp({
//该函数返回数据对象
data(){
return{
pess:'',
goods: {
name: '洗衣机',
price:0
}
}
},
watch: {
goods:{
//该回调函数在goods对象的属性改变时被调用
handler: function(newValue,oldValue){
if(newValue.price>=8000){
this.pess="价格太贵了,不可以采购!";
}
else{
this.pess="价格合适,可以采购!";
}
},
//设置为true,无论属性被嵌套多深,改变时都会调用handler函数
deep:true
}
}
//在指定的DOM元素上装载应用程序实例的根组件
}).mount('#app');
</script>
在 Chrome 浏览器中运行程序,在输入框中输入 860,下面会显示“价格合适,可以采购!”,如下图所示。
图 3 输入“860”效果
从上面的示例可以发现,页面初始化时监听器不会被调用,只有在监听的属性发生变化时才会被调用;如果要让监听器函数在页面初始化时执行,可以使用 immediate 选项,将其值设置为 true。
watch: {
goods:{
//该回调函数在goods对象的属性改变时被调用
handler: function(newValue,oldValue){
if(newValue.price>=8000){
this.pess="价格太贵了,不可以采购!";
}
else{
this.pess="价格合适,可以采购!";
}
},
//设置为true,无论属性被嵌套多深,改变时都会调用handler函数
deep:true,
//页面初始化时执行handler函数
immediate:true
}
此时在 Chrome 浏览器中运行程序,可以发现,虽然没有改变属性值,也调用了回调函数,显示了“价格合适,可以采购!”,如下图所示。
图 4 immediate选项的作用
在上面的示例中,使用 deep 属性深入监听,监听器会一层一层地往下遍历,给对象的所有属性都加上这个监听器,修改对象里面任何一个属性都会触发监听器里的 handler 函数。
在实际开发过程中,用户很可能只需要监听对象中的某几个属性,设置 deep:true 之后就会增大程序性能的开销。这里可以直接监听想要监听的属性,例如修改上面的示例,只监听 score 属性。
【实例四】监听器对象的单个属性。
<div id="app">
商品产地:<input type="text" v-model="goods.city">
<p>{{pess}}</p>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
//创建一个应用程序实例
const vm= Vue.createApp({
//该函数返回数据对象
data(){
return{
pess:'',
goods: {
name: '洗衣机',
city:''
}
}
},
watch: {
//监听goods对象的city属性
'goods.city':{
handler: function(newValue,oldValue){
if(newValue == "上海"){
this.pess="商品的产地是上海!";
}
else{
this.pess="商品的产地不是上海!";
}
},
//设置为true,无论属性被嵌套多深,改变时都会调用handler函数
deep:true
}
}
//在指定的DOM元素上装载应用程序实例的根组件
}).mount('#app');
</script>
在 Chrome 浏览器中运行程序,在输入框中输入“北京”,结果如下图所示。
图 5 输入“北京”的效果
注意,监听对象的属性时,因为使用了点号(.),所以要使用单引号(' ')或双引号(" ")将其包裹起来,例如"'goods.city'"。
ICP备案:
公安联网备案: