Skip to content

Vue3监视属性和watchEffect

  1. 与Vue2.x中的watch配置功能一致
  2. 两个小坑:
    • 监视reactive定义的响应式数据时: oldValue无法正确获取,默认开启了深度监视(deep配置失效)
    • 监视reactive定义的响应式数据中某个属性时: deep配置有效

1. 监视ref定义的数据

js
// 情况一:监视ref所定义的一个响应式数据, deep: true没必要,ref里面都是基本类型数据
  /* watch(sum, (newValue, oldValue) => {
    console.log('sum变了', newValue, oldValue);
  }, {immediate:true, deep: true}) */
  // 情况二:监视ref所定义的多个响应式数据, immediate为true表示立即监视
  watch([sum, msg], (newValue, oldValue) => {
    console.log('sum变了', newValue, oldValue);
  }, {immediate:true})

运行结果: Alt text

js
  let person = ref({
  name: 'jack',
  age: 33
})
watch(person.value, (newValue, oldValue) => {
  console.log('person变了', newValue, oldValue);
}, {immediate:true})

为何是person.value不是person呢? 因为ref实例只能检测当前表面的值(但是属性变了,实例对象的指针不变,所以不能监视到),也就是对象数据内部的属性无法监视,而person.value是一个Proxy对象(和reactive处理的对象类型一样),所以可以监视内部属性, 而监视person.value就是监视person, 因为ref处理对象就是将对象reactive处理然后包了一层ref 或者调整这样子可以监视所有属性:

js
 watch(person.value, (newValue, oldValue) => {
    console.log('person变了', newValue, oldValue);
  }, {deep:true}) 

Alt text

2. 监视reactive定义的数据

js
let person = reactive({
    name: 'jack',
    age: 33
})
  /* 情况三:监视reactive所定义的一个响应式数据,  */
  watch(person, (newValue, oldValue) => {
    console.log('person变了', newValue, oldValue);
  }, {immediate:true})

运行结果: Alt text 对于reactive定义的数据不开启深度监视:默认深度监视为true

js
let person = reactive({
    name: 'jack',
    age: 33,
    job:{
      j1:{
        salary: 20
      }
    }
})
watch(person, (newValue, oldValue) => {
console.log('person变了', newValue, oldValue);
}, {immediate:true})

Alt text 手动将deep:false, 深度监视对象将无效,比如监视多层级薪资job.j1.salary属性

3. 监视对象的一个属性

3.1 如果监视对象的一个属性:

比如监视person.age

js
/* 监视reactive所定义的一个响应式对象的属性 */
  watch(person.age, (newValue, oldValue) => { 
    console.log('person的age变了', newValue, oldValue);
  })

运行提示警告,并且监视无效 Alt text 需要更改监视代码:

js
/* 情况五:监视reactive所定义的一个响应式对象的属性, 
    属性需要是一个函数,不能直接xx.xx */
  watch(()=>person.age, (newValue, oldValue) => {
    console.log('person的age变了', newValue, oldValue);
  })

3.2 监视多个属性的变化:

js
  /* 情况六:监视reactive所定义的一个响应式对象的多个属性, 
    属性需要是一个函数,不能直接xx.xx */
    watch([()=>person.age, ()=>person.name], (newValue, oldValue) => {
    console.log('person的age或name变了', newValue, oldValue);
  })

3.3 监视多层属性的变化

传入一个函数,同时需要开启deep:true

js
/* 情况六:监视reactive所定义的一个响应式对象的多层次属性, 
属性需要是一个函数,不能直接xx.xx, */
watch([()=>person.job], (newValue, oldValue) => {
console.log('person的age,name变了', newValue, oldValue);
}, {deep:true})

3. watchEffect函数

  • watch的套路是:既要指明监视的属性,也要指明监视的回调
  • watchEffect的套路是: 不用指明监视的那个属性,监视的回调中用到那个属性,那就监视那个属性
  • watchEffect有点像computed:
    • 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值
    • 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值
js
// watchEffect所指定的回调中用到的数据只要发生变化, 则直接重新执行回调
watchEffect(()=>{
    const x1 = sum.value
    const x2 = person.value
    console.log('watchEffect配置的回调执行了')
})