开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
上面那篇文章介绍了计算属性,那么我们这边文章我们就来介绍一下watch属性。
监听属性
监听属性也叫侦听属性,是可以直接监听数据的,即可以监听基本类型变量,也可以监听对象属性。
1. 基本用法
<input type="text" v-model="firstName" />
watch: {
firstName: {
handler: function(newVal, oldVal) {
console.log('firstName变化了,这是最新的值:', newVal);
}
}
},
这时只要一输入值就能监听到firstName的变化
2. 即时监听
在有的应用场景中,我们需要页面从一开始的时候就开始监听变化,而不是只有在数据变化的时候才开始执行里面的handler函数,这时候就需要用到一个属性immediate。
watch: {
firstName: {
handler: function(newVal, oldVal) {
console.log('firstName变化了,这是最新的值:', newVal);
},
immediate: true
}
},
这时页面一挂载进来就能监听,执行handler函数
3. 深度监听
前面讲到的一些例子都是监听一些基本类型变量,很多时候我们需要监听到对象的变化,这时候就必须使用到另外一个属性deep。
<input type="text" v-model="person.name">
<input type="text" v-model="person.age">
data() {
return {
person: {
name: '',
age: 18
}
}
}
watch: {
person: {
handler: function(newVal) {
console.log('person变化了');
}
},
deep: true
},
上面这个例子只有加了deep属性才能监听到person的变化,否则是不能监听到,因为person的属性是个引用类型变量,person属性值存的实际上是一个地址,改变person对象的属性值对象本身是不变的,应用地址也不会改变,person就不会被监听到,只有加了deep属性才可以被监听到。
4. 简写形式
上面是watch的完整形式,如果只是想监听数据,而不需要使用deep属性和immediate属性的话,可以采用下面的简写属性。
// 完整形式
firstName: {
handler: function(newVal, oldVal) {
console.log('firstName变化了,这是最新的值:', newVal);
}
}
// 简写形式
firstName(newVal, oldVal) {
console.log('firstName变化了,这是最新的值:', newVal);
},
5. 原理
function initWatch (vm: Component, watch: Object) {
// 1.遍历watch
for (const key in watch) {
const handler = watch[key]
if (Array.isArray(handler)) {
for (let i = 0; i < handler.length; i++) {
createWatcher(vm, key, handler[i])
}
} else {
// 2.创建watcher
createWatcher(vm, key, handler)
}
}
}
function createWatcher (
vm: Component,
expOrFn: string | Function,
handler: any,
options?: Object
) {
//监听属性的值是一个对象,包含handler,deep,immediate
if (isPlainObject(handler)) {
options = handler
handler = handler.handler
}
//如果回调函数是一个字符串,从VM中获取
if (typeof handler === 'string') {
handler = vm[handler]
}
//expOrFn是key, options是watch的全部选项
return vm.$watch(expOrFn, handler, options)
}
6. watch可以使用异步函数
很多时候,监听数据变化后,我们需要进行一些异步操作,比如定时器回调:
firstName(newVal, oldVal) {
setTimeout(() => {
console.log('firstName变化了,这是最新的值:', newVal);
})
},
7. 计算属性和监听属性的区别
上面一篇文章我们介绍过计算属性,还用了姓和名列举了全名的案例,这个案例也可以通过watch监听来实现。
<input type="text" v-model="firstName" />
<input type="text" v-model="lastName" />
<div>{{fullName}}</div>
data () {
return {
firstName: '',
lastName: '',
fullName: ''
};
},
watch: {
firstName(newVal, oldVal) {
console.log('firstName变化了,这是最新的值:', newVal);
this.fullName = newVal + '-' + this.lastName;
},
lastName(newVal, oldVal) {
console.log('lastName变化了,这是最新的值:', newVal);
this.fullName = this.firstName + '-' + newVal;
}
},
从上面这个例子中我们可以看出:
- computed能完成的功能,watch都可以完成
- watch能完成的功能,computed不一定能完成。例如: watch可以进行异步操作(setTimeout, ajax, promise)
- 所有能被vue管理的函数,最好写成普通函数,这样this才是vm或组件实例对象
- 所有不被vue管理的函数(定时器的回调函数,ajax的回调函数,promise回调函数),最好写成箭头函数,这样this才是vm或组件实例对象