watch
简介:虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
注意点:不应该使用箭头函数来定义 watcher 函数
watch中的几个常见属性:
1. handler: 定义监听到键名发生变化后执行的回调
2. immediate:因为默认是监听到数据改变时,才会执行handler回调;如果我们想一开始就让他的变化回调handler执行,就需要使用`immediate: true`
3. deep:可以深度监听整个键名内部的所有属性
1. 基本使用
- 被监听的data中的键名对应键值类型:
String | Function | Object | Array
<!-- 基本使用示例1: -->
<body>
<div id="app">
<input v-model="count" />
</div>
<script>
new Vue({
el: '#app',
data: {
count: 10,
},
watch: {
// watch中实时监听的是 data中的 count键名,count键对应的键值是一个回调函数
// 回调函数接受两个参数,newVal是count变化后的值,oldValue是count变成newValue的前一个值
count: function (newVal, oldVal) {
console.log(`new: %s, old: %s`, newVal, oldVal);
}
}
})
</script>
</body>
<!-- 基本使用示例2:监听到变化之后可以操作 -->
<div>
<p>FullName: {{fullName}}</p>
<p>FirstName: <input type="text" v-model="firstName"></p>
</div>
<script>
new Vue({
el: '#root',
data: {
firstName: 'Dawei',
lastName: 'Lou',
fullName: ''
},
watch: {
firstName(newName, oldName) {
// 监听到firstName变化,操作之后赋值给fullName
this.fullName = newName + ' ' + this.lastName;
}
}
})
</script>
2. watch属性使用
// 示例2:监听data中的键名所对应的键值的各种类型
var vm = new Vue({
data: {
a: 1,
b: 2,
c: {
title:'my-blog',
categories:[]
},
d: 4,
e: {
f: {
g: 5
}
}
},
watch: {
a: function (newVal, oldVal) {
console.log(`new: %s, old: %s`, newVal, oldVal);
},
// 可以是方法名
b: 'someMethod',
c: function (newVal, oldVal) {
console.log("如果c对象中的某个属性发生了变化,我们这种直接监听c对象是监听不到变化的,因为c对象的指向并没有发生改变");
},
// 下面监听方式的缺点是,只要修改c对象中的任何一个属性(无论嵌套多深的属性),都会执行handler;这样会造成更多的性能开销
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
},
// 只监听某个对象的特定属性,'c.title' 字符串写法;这种方式的优点弥补了深度监听整个对象而造成了更多的性能开销
'c.title': function(newVal, oldVal){
}
// 因为默认是监听到数据改变时,才会执行handler回调;如果想一开始就让他的变化回调handler执行,就需要使用`immediate: true`
d: {
handler: 'someMethod',
immediate: true
},
// 你可以传入回调数组,当e发生变化时,这一组回调函数它们会被逐一调用;感觉有点像观察者模式
e: [
'handle1',
function handle2 (val, oldVal) { /* ... */ },
{
handler: function handle3 (val, oldVal) { /* ... */ },
/* ... */
}
],
}
})
vm.a = 2 // => new: 2, old: 1
3. watch中的异步操作
可以在watch中执行复杂的异步操作等;这些是computed不能胜任的。具体可以参考官网的案例
4. vm.$watch实例方法
注意:在变更 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变更之前值的副本
语法:vm.$watch( expOrFn, callback, [options] )
expOrFn:String ,可以是监听的字符串键名,或者监听函数(就像监听一个未被定义的计算属性)callback: Function 监听的键名发生变化后的回调options: { handler | immediate | deep)
// 示例1:
// 键路径
vm.$watch('a.b.c', function (newVal, oldVal) {
// 做点什么
})
// 示例2:
// 函数
vm.$watch(
function () {
// 表达式 `this.a + this.b` 每次得出一个不同的结果时
// 处理函数都会被调用。
// 这就像监听一个未被定义的计算属性
return this.a + this.b
},
function (newVal, oldVal) {
// 做点什么
}
)
5. watch注销
vm.$watch: 返回一个取消观察函数,用来停止触发回调
注意:组件选项中的watch中可以随着组件的销毁而销毁,而实例方法的vm.$watch(),我们需要手动销毁
var unwatch = vm.$watch('a', callback);
// 停止触发回调
unwatch()
本文使用 mdnice 排版