Vue中的监听器主要用于监测组件实例的数据变动,并依据该数据变动作出响应,如更新一个数据,或者发起异步请求从服务器端请求数据。与计算属性不同的是,监听器不需要返回新的数据,不能被当作数据属性使用,当需要在数据变化时执行异步或开销较大的操作时,使用监听器是最合适的。
监听器在Vue实例的选项对象的watch选项中定义。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>监听器</title>
</head>
<body>
<div id = "app">
千米 : <input type = "text" v-model="kilometers">
米 : <input type = "text" v-model="meters">
</div>
<p id="info"></p>
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm = Vue.createApp({
data() {
return {
kilometers: 0,
meters: 0
}
},
watch: {
kilometers(val) {
this.meters = val * 1000;
console.log("aaa");
},
// 监听器函数也可以接受两个参数,val是当前值,oldVal是改变之前的值
meters(val, oldVal) {
this.kilometers = val / 1000;
}
}
}).mount('#app');
</script>
</body>
</html>
我们编写了两个监听器,分别监听数据属性kilometers和meters的变化,当其中一个数据属性的值发生改变时,对应的监听器就会被调用,经过计算得到另一个数据属性的值。 渲染结果如下,在“千米”或“米”输入框中输入数据,可以看到另一个输入框中的数据也会跟着改变。
监听器在定义时,除了直接写一个函数外,还可以接一个方法名。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
年龄:<input type="text" v-model="age">
<p v-if="info">{{info}}</p>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm=Vue.createApp({
data(){
return{
age:0,
info:''
}
},
methods:{
checkAge(){
if(this.age>=18){
this.info='已成年';
}else{
this.info='未成年';
}
}
},
watch:{
age:'checkAge'
}
}).mount('#app');
</script>
</body>
</html>
渲染结果:
监听器还可以监听一个对象的属性变化,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
年龄:<input type="text" v-model="person.age">
<p v-if="info">{{info}}</p>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm=Vue.createApp({
data(){
return{
person:{
name:'lisi',
age:0
},
info:''
}
},
watch:{
//该回调会在person对象的属性改变时被调用,无论该属性被嵌套多深
person:{
handler(val,oldVal){
if(val.age>=18){
this.info='已成年';
}else{
this.info='未成年';
}
},
deep:true,
}
}
}).mount('#app');
</script>
</body>
</html>
要注意在监听对象属性时,使用了两个新的选项:handler
和deep
,前者用于定义当数据变化时调用的监听器函数,后者主要在监听对象属性变化时使用,如果该选项的值为true
,表示无论该对象的属性在对象中的层级有多深,只要该属性的值发生变化,都会被监测到。
监听器函数在初始渲染时并不会被调用,只有在后续监听器的属性发生变化时才会被调用;如果要让监听去函数在监听开始后立即执行,可以使用immendiate
选项,将其值设置为true
.例如:
watch:{
//该回调会在person对象的属性改变时被调用,无论该属性被嵌套多深
person:{
handler(val,oldVal){
if(val.age>=18){
this.info='已成年';
}else{
this.info='未成年';
}
},
deep:true,
immediate:true //让监听器函数在监听开始后立即执行
}
}
当页面加载后,就会立即显示”未成年“。