1、监听器:可以监听data中值的变化,一般是监听data中的某个属性
特点:更加灵活,通用的api。watch中可以执行任何逻辑,如函数节流,ajax异步获取数据,操作dom
<template>
<div class="compute">
<h1>监听普通属性</h1>
<!-- v-model 视图和数据的双向绑定 -->
<span>姓名:</span><input type="text" v-model="userName">
<p v-text="userName"></p>
<span>年龄:</span><input type="text" v-model="age">
<p v-text="age"></p>
<p v-text="infos"></p>
</div>
</template>
<script>
export default {
name:'compute',
data(){
return{
userName:'terry',
age:13,
infos:''
}
},
watch:{
// 监听userName的变化
// 有两个参数,now表示变化后的值,old表示变化前的值
userName:function(now,old){
console.log('修改前的值',old)
console.log('修改后的值',now)
this.infos='我的姓名:' +this.userName+',年龄'+this.age;
},
//监听age的变化
age:function(now,old){
console.log('修改前的值',old)
console.log('修改后的值',now)
this.infos='我的姓名:' +this.userName+',年龄'+this.age;
}
}
}
</script>
<style lang="less" scoped>
</style>
2、监听类型:
浅监听:监听基本变量
深监听:deep:true
是关键,在Vue的文档中有说明:为了发现对象内部值的变化,可以在选项参数中指定 deep: true 。注意监听数组的变动不需要这么做。
3、问题
当数组或者对象只是单一的值改变时,并不会出发watch中的事件。
在找问题过程中,发现当数组使用push一类的方法时,会触发watch,如果只是单一改变,如object[index] = newData,并不会触发,而对象同理。
解决方法:
使用vue的set方法
即 this.$set(Object,index,newdata)
Object为你需要改变的数组,index为要改变的数组下标,newdata为新值。
这样的话,watch中的监听事件就会被触发。
4、监听对象
<h1>监听对象</h1>
<span>姓名:</span><input type="text" v-model="obj.name">
<p v-text="obj.name"></p>
data(){
return{
obj:{
name:'tom'
}
}
},
watch:{
// 直接监听对象
//将obj变为'obj.name'是直接监听对象的属性
obj:{
// handler表示默认执行的函数
handler(now,old){
console.log('修改前的值',old)
console.log('修改后的值',now)
},
// 表示深度监听
// true:表示handler函数会执行
// false:表示handler函数不会执行
deep:true
}
4、计算属性和监听属性的区别
1)计算属性性能更优。一个监听属性只能监听一个属性的变化,如果要同时监听多个,就要写多个监听属性,而计算属性可以同时监听多个数据变化
2)监听属性可获取改变之前的属性值
3)计算属性能做的,监听属性都能做,反之不行
4)能用计算属性尽量用计算属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监听器</title>
<!-- 导入vue -->
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
</head>
<body>
<div id="app">
{{a}}
<input type="text" v-model="a">
<br>
{{obj}}
<div>
<input type="text" v-model="obj.a">
<input type="text" v-model="obj.b">
</div>
</div>
<script>
new Vue({
el:"#app",
data:{
a:1,
obj:{a:"", b:""}
},
watch:{
"a":function(n,o){
console.log("a的值发生了变化",n,o);
}, //a的值会发生变化
'obj':function(n,o){
console.log("obj的值发生了变化",n,o);
}, //obj的值不发生变化 ,监听不到,obj为指针,内容发生变化,指针不便,引用传值
'obj.a':function(n,o){
console.log("obj的值发生了变化",n,o);
}, //a的值会发生变化
"obj":{
handler:function(n,o){
console.log("obj的值发生了变化",n,o);
},
deep:true
} //发生改变
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监听机制</title>
<!-- 导入vue -->
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="https://cdn.bootcss.com/lodash.js/4.17.15/lodash.js"></script>
</head>
<body>
<div id="app">
<button @click="change">change</button>
{{obj}}
<div>
<ul>
<li v-for="l in list">{{l}}</li>
</ul>
</div>
</div>
<script>
new Vue({
el:"#app",
data:{
obj:{
name:"terry",
age:12
},
list:[
{id:1,title:"hello"},
{id:2,title:"world"},
{id:3,title:"name"}
]
},
watch:{
obj:function(now,old){
// alert(JSON.stringify(now));
}
},
methods:{
change(){
this.obj = Object.assign({},this.obj)
this.obj.age++;
_.remove(this.list,item => item.id===2 )
}
}
})
</script>
</body>
</html>