一,侦听器的引入
之前就已经学到了,一旦vue实例对象中的数据发生了变化,页面上对应的数据也会随之发生变化,为了业务需要,常常需要对数据进行二次处理,为了保证数据实时变化,所以引入了侦听器的概念,对应的数据一旦发生变化。就会执行这里定义好的对应函数。
二,一个小案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="css/base.css"/>
<style type="text/css">
#app{
width: 10%;
margin: 200px auto;
border: 1px solid #ccc;
line-height: 40px;
padding: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="box">
<span>姓:</span>
<input type="text" v-model="surName"/>
<br>
<span>名:</span>
<input type="text" v-model="name"/>
<br>
<span>全名:</span>
<span>{{totalName}}</span>
</div>
</div>
<script type="text/javascript" src="./js/vue.min.js"></script>
<script type="text/javascript">
var vm=new Vue({
el: "#app",
data:{
surName:"",
name:"",
totalName:""
},
computed:{},
methods:{},
watch:{
//这里是对surName这个数据的监听,一旦发生变化,就执行这里的函数
surName:function(){
this.totalName=this.surName+this.name
},
//这里是对name这个数据的监听,一旦发生变化,就执行这里的函数
name:function(){
this.totalName=this.surName+this.name
},
}
})
</script>
</body>
</html>
三,侦听器的应用场景:处理异步的操作
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="css/base.css"/>
<style type="text/css">
#app{
width: 20%;
margin: 200px auto;
border: 1px solid #ccc;
line-height: 40px;
padding: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="box">
<span>姓名:</span>
<input type="text" v-model.lazy="name"/>
<span>{{msg}}</span>
</div>
</div>
<script type="text/javascript" src="./js/vue.min.js"></script>
<script type="text/javascript">
var vm=new Vue({
el: "#app",
data:{
name:"",
msg:""
},
computed:{},
methods:{
checkName:function(name){
//调用接口,但是可以使用定时任务的方式来模拟接口调用
var that=this;
//因为这里是setTimeout函数,this指向的是window,而在这之前的this还是vm
setTimeout(function(){
//模拟接口调用
if(name=='lingxu'){
that.msg="用户名已经存在,请更换一个"
}else{
that.msg="用户名可以使用"
}
},500)
}
},
watch:{
name:function(val){
//调用后台接口验证用户名的合法性
//这里的参数,实参实际上就是当前的name值
this.checkName(val)
this.msg="正在验证中……"
},
}
})
</script>
</body>
</html>
四,让watch在页面初始化时也执行一次
immediate(立即处理 进入页面就触发)
<body>
<div id="app">
<input type="text" v-model="num">
</div>
<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
num: 1
},
watch: {
num: {
// 数据发生变化就会调用这个函数
handler(newVal, oldVal) {
console.log('oldVal:', oldVal)
console.log('newVal:', newVal)
},
// 立即处理 进入页面就触发
immediate: true
}
}
})
</script>
</body>
这里需要注意的是,这个侦听器的第一次执行会在create生命周期之前,所以通过create获取的参数监听将会报错。
五,deep(深度监听)
对象和数组都是引用类型,引用类型变量存的是地址,地址没有变,所以不会触发watch。这时我们需要进行深度监听,就需要加上一个属性 deep,值为 true
<body>
<div id="app">
<input type="button" value="更改名字" @click="change">
</div>
<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
food: {
id: 1,
name: '冰激凌'
}
},
methods: {
change() {
this.food.name = '棒棒糖'
}
},
watch: {
// 第一种方式:监听整个对象,每个属性值的变化都会执行handler
// 注意:属性值发生变化后,handler执行后获取的 newVal 值和 oldVal 值是一样的
food: {
// 每个属性值发生变化就会调用这个函数
handler(newVal, oldVal) {
console.log('oldVal:', oldVal)
console.log('newVal:', newVal)
},
// 立即处理 进入页面就触发
immediate: true,
// 深度监听 属性的变化
deep: true
},
// 第二种方式:监听对象的某个属性,被监听的属性值发生变化就会执行函数
// 函数执行后,获取的 newVal 值和 oldVal 值不一样
'food.name'(newVal, oldVal) {
console.log('oldVal:', oldVal) // 冰激凌
console.log('newVal:', newVal) // 棒棒糖
}
}
})
</script>
</body>