2022-10-21 vue3 watch watchEffec

2022-10-21  本文已影响0人  忙于未来的民工

vue3中watch的用法,比2复杂很多。

function watch<T>(
  source: WatchSource<T>,
  callback: WatchCallback<T>,
  options?: WatchOptions
): StopHandle

watch函数接受三个参数,
第一个监听的数据源:可以是一个函数返回一个值、ref、reactive、或者由以上三种组成一个数组(监听多个数据源)
第二个数据源变动时执行的回调函数,执行时机默认是渲染之前
第三个类似于2的参数,immediate、deep、flush(回调执行时机)

1:监听基本数据类型和一个函数,直接使用即可。

  const a = reactive({b: 1})
  watch(
    () => a.b,
    (value, oldValue) => {
      console.log(value, oldValue)
    }
  )

2:监听多个数据源

  const a = ref('aaa')
  const b = ref('bbbb')

  watch([a, b], ([a, b], [preva, prevb]) => {
  })

注意:如果a和b在渲染之前都被改变,只执行一次,若一个在渲染前一个在渲染后,则回调执行两次

3:监听引用数据源,数据源定义分为ref和reactive
ref定义,数组中为基本数据类型,只能获取当前值,
如果数组中是引用数据类型,需要加deep才能获取当前值:

const arrayRef = ref([1, 2, 3, 4])
watch(
 arrayRef,
 (newValue, oldValue) => {
   console.log('new', newValue, 'old', oldValue)
 },
)

ref定义,获取老值和新值,
如果数组中是引用数据类型,需要加deep才能获取当前值和老值:

const arrayRef = ref([1, 2, 3, 4])
watch(
  () => [...arrayRef.value],
  (newValue, oldValue) => {
   console.log('new', newValue, 'old', oldValue)
  },
)

reactive 定义,只能获取新值
如果数组中是引用数据类型,不需要加deep,reactive默认添加:

const arrayRef = reactive([1, 2, 3, 4])
watch(arrayRef, (newValue, oldValue) => {
  console.log('new', newValue, 'old', oldValue)
})

reactive 定义,可以获取新值和老值,
如果数组中是引用数据类型,需要加deep才能获取当前值:

const arrayRef = reactive([1, 2, 3, 4])
watch(
  () => [...arrayRef],
  (newValue, oldValue) => {
    console.log('new', newValue, 'old', oldValue)
  }
)

总结:如果直接监听数据源,无法获取老值,如果监听get函数,可以获取老值,如果数组中是引用数据类型,ref定义需要添加deep,reactive定义直接监听不需要加,监听get函数需要加。

watchEffect:

function watchEffect(
  effect: (onCleanup: OnCleanup) => void,
  options?: WatchEffectOptions
): StopHandle

type OnCleanup = (cleanupFn: () => void) => void

interface WatchEffectOptions {
  flush?: 'pre' | 'post' | 'sync' // 默认:'pre'
  onTrack?: (event: DebuggerEvent) => void
  onTrigger?: (event: DebuggerEvent) => void
}

type StopHandle = () => void

接受两个参数,
第一个是回调函数,在代码初始化时会立即执行,并且会同时收集依赖。回调函数有一个参数(OnCleanup),主要作用是在当该回调函数在执行任务时(还未执行完,比如在函数中包含异步函数),再次触发了该回调,这个时候在执行该回调之前会执行一次OnCleanup钩子。OnCleanup的执行时机可以简单理解为当该回调执行一次后,在该回调下次执行之前执行。
第二个是options参数。
例子:


const a = reactive({ b: 1 })
watchEffect(OnCleanup => {
  console.log(a.b) // 收集依赖
  let timer = setTimeout(() => {
    console.log(2222) // 理论上应该执行两次,但是因为OnCleanup 所以 执行一次
  }, 8000)
  OnCleanup(() => {
    console.log('执行OnCleanup')
    clearTimeout(timer)
  })
})
setTimeout(() => {
  a.b = 3
}, 5000)
上一篇下一篇

猜你喜欢

热点阅读