watch

监听数据源的变化,并执行回调函数

  • 参数1,数据源
  • 参数2,回调函数(newVal, oldVal)
  • 参数3,配置对象
    • deep: 是否开启深度监听
    • immediate: 是否立即执行一次

普通类型包装的Ref对象

监听多个可以用数组的形式表示

1
2
3
4
5
6
7
let msg1 = ref('')
let msg2 = ref('')

watch([msg1, msg2], (newVal, oldVal) => {
console.log('old:', oldVal);
console.log('new:', newVal);
})

对象类型包装的Ref对象

需要开启深度监听,才能监听到对象属性的变化。不过开启深度监听后,oldVal会与newVal相同,也就是说不能知道旧的值。可能是vue底层实现的问题。

1
2
3
4
5
6
7
8
9
10
11
12
let deepMsg:Ref = ref({
name: 'ler-jiu',
age: 18
})


watch(deepMsg, (newVal, oldVal) => {
console.log('old:', oldVal);
console.log('new:', newVal);
}, {
deep:true,
})

监听单个属性

如果想要监听对象属性的变化,并且能够查看oldVal,可以选择监听对象的属性。这里要写成函数的形式,将想要监听的属性返回,也可以写成数组形式,一次监听多个属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let deepMsg = ref({
name: 'ler-jiu',
age: 18
})

const changeDeepMsg = () => {
console.log('change')
deepMsg.value = {
name: 'ler-jiu',
age: 18
}
}

watch(deepMsg, (newVal, oldVal) => {
console.log('old:', oldVal);
console.log('new:', newVal);
}, {
deep:true,
})

watch(() => [deepMsg.value.name, deepMsg.value.age], (newVal, oldVal) => {
console.log('old', oldVal);
console.log('new', newVal);
})

如果只需要知道改变后的新值,对对象进行监听,开启deep就足够了。

如果需要知道oldVal,选择下面的写法。

如果对象的类型已经约定好了,即这个变量不能被赋值为不同类型的对象,那么监听属性其实是比较通用的,因为无论怎么改变都只是属性值的改变。

如果对象类型可以改变,那么对属性的监听是不合理的,毕竟监听的属性都可能消失了。这时上面的写法,可以通过对oldValnewVal的比较来判断是对值的修改还是对对象的修改(上面提到的,对值修改会导致oldValnewVal相同),当然具体情况要结合deep是否开启来分析,这里只是提一下这种想法。

对Reactive对象的监听

与上面不同的是,reactive默认强制开启deep,即便手动设置为false也没用。