0%

watch

watch()

监视属性watch:

1 当被监视的属性变化时(也可以监视计算属性),回调函数自动调用,进行相关操作

2 监视的属性必须存在才能好进行监视

3 监视的两种写法:

(1)在Vue.createApp时传入watch配置

(2)通过vm.$watch监视

4 深度监视

(1)Vue中的watch默认不监视对象内部值的改变(一层)

(2)配置deep为true,可以检测对象内部值改变(多层)

监视多级结构中某个属性的变化:’number.a’

监视多级结构中所有属性第1变化,用deep:true

PS:(1)Vue自身可以检测对象内部值的改变但是Vue提供的watch默认不可以

(2)使用watch时根据数据的具体结构,决定是否采用深度监视

vm.$watch(expOrFn,callback,[options])

  • expOrFn:{string/Function}
  • callback:{Function/Object}
  • options:{Object}
    1. deep:{boolean}
    2. immediate:{boolean}

返回值:unwatch函数

用处:观察Vue实例上的一个表达式或者一个函数计算结果的变化,回调函数得到的参数为新值和旧值。表达式只接受简单的键路径,对于复杂表达式,用函数取代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//HTML
<div id="app">
{{a}},{{b}}
</div>
//键路径
<script type="text/javascript">
var vm=new Vue({
el:"#app",
data:{
a:{value1:'hello'},
b:{value2:'beautiful'}
}

});
vm.$watch('b.value2',function(newVal,oldVal){
console.log(newVal,oldVal);
});
vm.b.value2='bind';//bind beautiful
//修改对象内部的值但是侦听的是对象,对其属性或元素的更改不会触发侦听器,因为他们引用相同对象
vm.$watch('a',function(newVal,oldVal){
console.log(newVal,oldVal);
});
vm.a.value1='hei';//没有侦听到
//为了发现对象内部值的变化,可以在选项参数中指定 deep: true。这个选项同样适用于监听数组变更。
vm.$watch('a',function(newVal,oldVal){
console.log(newVal,oldVal);
},{deep:true});
vm.a.value1='hei';//
//在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调
vm.$watch('a',function(newVal,oldVal){
console.log(newVal,oldVal);
},{immediate:true});
vm.a={}//{_ob_:Observer}undefined {_ob_:Observer}{_ob_:Observer}
</script>

在带有immediate选项时不能在第一次回调时取消侦听给定的property

1
2
3
4
5
6
7
const unwatch=vm.$watch(
'a',
function(newVal,oldVal){
console.log(newVal,oldVal);
unwatch()
},{immediate:true}
)//报错

要在回调函数里调用一个取消侦听的函数应该先检查其函数的可用性

1
2
3
4
5
6
7
8
let unwatch=null;
unwatch=vm.$watch(
'a',
function(newVal,oldVal){
console.log(newVal,oldVal);
if(unwatch){unwatch();}
},{immediate:true}
)

Vue3中的watch

两个“坑”:

  1. watch监视的是reactive定义的响应式数据则无法正确获得oldValue,watch监视的是reactive定义的响应式数据则强制开启深度监视,只能获取newValue,无法获取oldValue

  2. 监视reactive定义的某个对象中的属性(也是对象),deep有效,仍然无法获取oldValue

关于.value:

  1. 如果ref定义的是一个数字或者字符,比如ref(0)不能用.value
  2. 如果ref定义的是一个对象,则里面的属性本质上是由reactive定义,如果要监视里面的属性则得用.value,.value后由reactive定义,则自动开启深度监视,或者开启深度监视
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 setup(){
let person=reactive({
firstName:"张",
lastName:"三",
fullName:'',
job:{
one:'doctor',
tow:'teacher'
}

})
let sum=ref(0)
let msg=ref("你好呀")
//情况一:监视ref定义的响应式数据
watch(sum,(newValue,oldValue)=>{
console.log("sum变化了",newValue,oldValue)
})
//情况二:监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{
console.log("sum或msg变化了",newValue,oldValue)
})
//情况三:监视reactive定义的响应式数据:若watch监视的是reactive定义的响应式数据则无法正确获得oldValue,watch监视的是reactive定义的响应式数据则强制开启深度监视,只能获取newValue,无法获取oldValue
watch(person,(newValue,oldValue)=>{
console.log("person变化了",newValue,oldValue)
},{deep:false})//deep配置无效
//情况四:监视reactive定义的响应式数据中的某个属性
watch(()=>person.firstName,(newValue,oldValue)=>{
console.log("person的firstName变化了",newValue,oldValue)
})

//情况五:监视reactive定义的一个响应式数据中的某些属性
watch([()=>person.firstName,()=>person.lastName],(newValue,oldValue)=>{
console.log("person的firstName/lastName变化了",newValue,oldValue)
})
//特殊情况监视reactive定义的某个对象中的属性(也是对象),deep有效,仍然无法获取oldValue
watch(()=>person.job,(newValue,oldValue)=>{
console.log("person的job变化了",newValue,oldValue)
},{deep:true})
person.fullName=computed({
get(){
return person.firstName+'-'+person.lastName

},
set(value){
const nameArr=value.split('-')
person.firstName=nameArr[0]
person.lastName=nameArr[1]

}
})
watch()
return {
person,
sum,
msg
}
}