字节笔记本字节笔记本

Vue3 watchEffect vs watch 区别

2022-04-02

Vue3中,`watch`需要显式指定依赖源,而`watchEffect`自动收集依赖源并立即执行回调函数,且能自动追踪新增依赖。

  • watch- 显式指定依赖源,依赖源更新时执行回调函数

  • watchEffect - 自动收集依赖源,依赖源更新时重新执行自身

watchEffect 相当于将 watch 的依赖源和回调函数合并,当任何你有用到的响应式依赖更新时,该回调函数便会重新执行。不同于 watchwatchEffect 的回调函数会被立即执行(即 { immediate: true }

watch 不同的一点是,在 watchEffect 中依赖源会被重复执行,动态新增加的依赖也会被收集,例如

watch

const refVal = ref(0)
const reactiveVal = reactive({name: '小明', age: 18, job: {salary: 20})

// 情况1:参数1不是函数,监听的主要是响应式对象的变化
// 监听的是对象时,强制开启deep: true
// 监听的是对象时,newVal与oldVal一样,算是bug?
watch(refVal, (newVal, oldVal) => {}, {})
watch(reactiveVal, (newVal, oldVal) => {}, {})
watch(reactiveVal.job, (newVal, oldVal) => {}, {})
watch([refVal, reactiveVal], (newVal, oldVal) => {}, {})

// 情况2:参数1是函数,监听的主要是值的变化
watch(() => refVal.value, (newVal, oldVal) => {}, {})
watch(() => reactiveVal.name, (newVal, oldVal) => {}, {})
watch(() => [refVal, reactiveVal.name], (newVal, oldVal) => {}, {})

watchEffect

// 作为参数传入的函数立即执行
// 监听的是值
const sum = ref(0)
const stop = watchEffect((onInvalidate) => {
  console.log(sum.value)
  // 该函数立即执行一次
  // 监听值而不是响应式对象的变化
  // 函数中用到了哪些数据(如sum),这些数据发生改变时,该函数执行
  // 当函数中有一些副作用时,如当数据变化时,请求数据,那么就会出现问题:及监听的数据不停变化,副作用不断进行,onInvalidate函数的作用就是取消之前的一些操作
  onInvalidate(() => {
    // 取消一些之前的副作用
    // onInvalidate函数作用的外部函数中首先执行:及先执行onInvalidate函数传入的参数,再执行console.log(0)
  })
})

// 执行stop函数时,会清除监听
stop()