watch 和 watchEffect 的使用

ref 监听

监听 ref 值,ref.value 是基本数据类型

  /**
   * 通过 myName.value 更换值时会触发
   * 通过 ref 定义基本数据类型时,不能监听 xxx.value 因为这获取的就是一个具体值
   */
  let myName = ref('苹果')
  
  watch(myName, (newValue, oldValue) => {
    // myName: 香蕉 苹果
    console.log('myName:', newValue, oldValue)
  })
  
  myName.value = '香蕉'

监听 ref 值,ref.value 是引用数据类型

  /**
   * 当监听的ref是引用类型时,仅通过 rex.value 更换值时才会触发监听
   * 如果需要监听引用类型内部的变化,则需要添加深度监听 { deep: true }
   */
  let myRefObj = ref({ name: '苹果' })
  
  watch(myRefObj, (newValue, oldValue) => {
    console.log('myRefObj:', newValue, oldValue)
  })
  
  myRefObj.value = '香蕉'

监听 ref.value 值

ref.value 必须是引用类型。如果 ref.value 是基本数据类型,则无法监听

  /**
   * myRefObj.value 为对象,等同于 监听一个 reactive 对象,侦听器会自动启用深层模式
   * 当给 myRefObj.value 赋值新对象时监听不会执行,但 template 中数据还是响应式的
   */
  let myRefObj = ref({name: '苹果'})

  watch(myRefObj.value, (newValue, oldValue) => {
    console.log('myRefObj:', newValue, oldValue)
  })

  myRefObj.value.name = '香蕉' // 会监听到
  //  myRefObj.value = {name: '栗子'} // 不会监听到

reactive 监听

监听 reactive 对象的基本数据类型

  /**
   * 通过 myObj.name 更换值时会触发(myObj.name 需是基本数据类型)
   * 当直接侦听一个响应式对象时,侦听器会自动启用深层模式
   */
  let myObj = reactive({ name: '小明', age: 20, info: { address: 'bj' } })
  
  watch(myObj, (newValue, oldValue) => {
    // myObj:都是 {name: '小红', age: 20}
    console.log('myObj:', newValue, oldValue)
  })

  myObj.name = '小红'

监听 reactive 对象的引用数据类型

  /**
   * 监听 myObj.info 值
   * 仅更换 myObj.info 内的数据时才会被监听到
   * 通过 reactive 定义引用类型时,如果通过 xxx.xx 获取的是基本类型时,则不能监听 xxx.xx 数据;如果通过 xxx.xx 获取的是引用类型时,则可以监听 xxx.xx 数据
   */
  let myObj = reactive({ name: '小明', age: 20, info: { address: 'bj' } })
  
  watch(myObj.info, (newValue, oldValue) => {
    console.log('myObj.info:', newValue, oldValue)
  })

  myObj.info.address = 'sh'

函数监听

一个函数,必须返回一个值,只有当值发生变化时,才会触发回调

监听 ref.value 数据时

  • 当 ref.value 返回基本数据类型时,通过ref.value值就可以监听到
  • 当 ref.value 返回引用数据类型时,仅通过修改 ref.value值时可以被监听到,当修改对象内部值时是无法被监听到,此时需要添加 { deep: true} 启用深度监听
  let myName = ref('苹果')
  
  watch(
    () => myName.value,
    (newValue, oldValue) => {
      console.log('myName:fn:', newValue, oldValue)
    }
  )

  myName.value = '香蕉'

监听 ref 对象时

不管是监听 reactive 对象,还是监听 ref 对象,都不会自动启用深度监听,必须通过添加 { deep: true },这样当修改对象内部数据时才会被监听到

  let myName = ref('苹果')
  
  watch(
    () => myName,
    (newValue, oldValue) => {
      console.log('myName:deep:fn:', newValue, oldValue)
    },
    { deep: true }
  )

  myName.value = '香蕉'

监听 reactive 数据的基本类型时

  let myObj = reactive({ name: '小明', age: 20, info: { address: 'bj'} })

  watch(
    () => myObj.name,
    (newValue, oldValue) => {
      console.log('myObj:fn:', newValue, oldValue)
    }
  )

  myObj.name = '小红'

监听 reactive 数据的引用类型时

  /**
   * 这里返回的是对象对应的地址
   */
  let myObj = reactive({ name: '小明', age: 20, info: { address: 'bj'} })

  watch(
    () => myObj.info,
    (newValue, oldValue) => {
      console.log('myObj:deep:fn:', newValue, oldValue)
    },
    { deep: true }
  )

  myObj.name = '小红'

注意:myObj.info 是一个对象,当启用深度监听后,修改 myObj.info 为另一个对象或修改 myObj.info 内部属性的值时都会触发回调

侦听多个来源

  // 当侦听多个来源时,回调函数接受两个数组,分别对应来源数组中的新值和旧值
  watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
    /* ... */
  })

watchEffect使用

watchEffect 首次加载先执行一次,即便是空函数也会执行

  watchEffect(() => {
  })

watch 和 watchEffect 特点

watch特点

  • 懒执行,仅当数据变化时执行(immediate: true 除外)
  • 更加明确需要侦听的数据源,更精准的控制回调函数的触发时机
  • 可以访问所侦听状态的前一个值和当前值

watchEffect特点

  • 首次加载会执行一次,即便是空函数
  • 自动追踪所有能访问到的响应式属性,任一属性发生变化都会触发回调函数
  • 无法获取前一个值和当前值

flush: 调整回调函数的刷新时机

  • pre: 默认值,回调会在 Vue 组件更新之前被调用,此时在回调中访问的 DOM 将是 Vue 更新之前的状态
  • post: Vue 组件更新之后调用侦听器的回调函数。此时在回调函数中访问的 DOM 将是 Vue 更新之后的状态
  • sync: 同步执行,当侦听到变化时回调函数立即执行,执行完成后才接着执行后面的代码

你可能感兴趣的:(Vue3,watch,watchEffect)