vue3中的watch源码浅析

本文通过对Vue3的watch源码分析,探讨了watch的工作原理。watch不仅支持多数据源观测,也适用于Ref、ComputedRef及effect函数。核心逻辑位于doWatch方法,包括获取初始值、设置回调函数、依赖收集等步骤,确保了数据变更时的响应式更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

watch源码浅析

通过对reactive的解读中明白了在vue中将被响应式系统收集的依赖为组件更新,computed,watch三类。而watch的具体实现具体是怎样的?这就是本次学习的目标。

依然通过暴露的composition api入手,从watch方法看整个watch的实现过程。
一开始就是连续的4个函数重载,就知道vue3中的watch肯定也还是有所变化的了。

// apiWatch.ts
// overload #1: array of multiple sources + cb
export function watch<
  T extends MultiWatchSources,
  Immediate extends Readonly<boolean> = false
>(
  sources: [...T],
  cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
  options?: WatchOptions<Immediate>
): WatchStopHandle

// overload #2 for multiple sources w/ `as const`
// watch([foo, bar] as const, () => {})
// somehow [...T] breaks when the type is readonly
export function watch<
  T extends Readonly<MultiWatchSources>,
  Immediate extends Readonly<boolean> = false
>(
  source: T,
  cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
  options?: WatchOptions<Immediate>
): WatchStopHandle

// overload #2: single source + cb
export function watch<T, Immediate extends Readonly<boolean> = false>(
  source: WatchSource<T>,
  cb: WatchCallback<T, Immediate extends true ? (T | undefined) : T>,
  options?: WatchOptions<Immediate>
): WatchStopHandle

// overload #3: watching reactive object w/ cb
export function watch<
  T extends object,
  Immediate extends Readonly<boolean> = false
>(
  source: T,
  cb: WatchCallback<T, Immediate extends true ? (T | undefined) : T>,
  options?: WatchOptions<Immediate>
): WatchStopHandle

从以上的函数重载可以知道watch方法可以为多数据源,单一数据源提供观测。并且数据源应该是vue3中的Ref实例,ComputedRef实例,或者effect函数。

// apiWatch.ts
// implementation
export function watch<T = any, Immediate extends Readonly<boolean> = false>(
  source: T | WatchSource<T>,
  cb: any,
  options?: WatchOptions<Immediate>
): WatchStopHandle {
   
   
  // dev环境下,传入的cb不是函数就输出提示
  if (__DEV__ && !isFunction(cb)) {
   
   
    warn(
      `\`watch(fn, options?)\` signature has been moved to a separate API. ` +
        `Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` +
        `supports \`watch(source, cb, options?) signature.`
    )
  }
  return doWatch(source as any, cb, options)
}
// 转换watch的过程比较长,就截取一些关键内容,以下代码非完整源码
function doWatch(
  source: WatchSource | WatchSource[] | WatchEffect | object,
  cb: WatchCallback | null,
  {
   
    immediate, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ,
  instance = currentInstance
): WatchStopHandle {
   
   
  // dev环境下的部分提示
  if (__DEV__ && !cb) {
   
   
    // 打印提示的代码
  }
  // 提示非法数据源,合法的数据源是:getter/effect function, ref, reactive object
  const warnInvalidSource = (s: unknown) => {
   
   
    warn(
      `Invalid watch source: `,
      s,
      `A watch source can only be a getter/effect function, a ref, ` +
        `a reactive object, or an array of these types.`
    )
  }
  // 以getter函数获取数据源的值
  let getter: () => any
  let forceTrigger = false
  if (isRef(source)) {
   
   
    // 数据源是ref
    getter = () => (source as Ref).value
    forceTrigger = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值