Home / Function/ doWatch() — vue Function Reference

doWatch() — vue Function Reference

Architecture documentation for the doWatch() function in apiWatch.ts from the vue codebase.

Function typescript CompilerSFC SfcParser calls 10 called by 4

Entity Profile

Dependency Diagram

graph TD
  880ea200_f528_af26_3f6f_c77fc2f21647["doWatch()"]
  27ac0da7_848d_2b52_5b63_5eb582827a0b["watchEffect()"]
  27ac0da7_848d_2b52_5b63_5eb582827a0b -->|calls| 880ea200_f528_af26_3f6f_c77fc2f21647
  cff31b8c_9131_2f34_6ed5_01a93ff663ec["watchPostEffect()"]
  cff31b8c_9131_2f34_6ed5_01a93ff663ec -->|calls| 880ea200_f528_af26_3f6f_c77fc2f21647
  fdfac1cb_5889_15fa_76dd_977bb613a1f7["watchSyncEffect()"]
  fdfac1cb_5889_15fa_76dd_977bb613a1f7 -->|calls| 880ea200_f528_af26_3f6f_c77fc2f21647
  de6a892d_79ff_ad64_7fc3_5f2fc0b51eb0["watch()"]
  de6a892d_79ff_ad64_7fc3_5f2fc0b51eb0 -->|calls| 880ea200_f528_af26_3f6f_c77fc2f21647
  de6a892d_79ff_ad64_7fc3_5f2fc0b51eb0["watch()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| de6a892d_79ff_ad64_7fc3_5f2fc0b51eb0
  b6fb2fe6_1e20_8aa7_252b_c7c3e62b0e26["depend()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| b6fb2fe6_1e20_8aa7_252b_c7c3e62b0e26
  f00627f9_f6f9_0415_07cf_adaab8eba795["isRef()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| f00627f9_f6f9_0415_07cf_adaab8eba795
  f510a797_01c9_4b79_7634_e77112e3ed58["isShallow()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| f510a797_01c9_4b79_7634_e77112e3ed58
  7673a120_6161_8253_592c_2125fb6cfd5d["isReactive()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| 7673a120_6161_8253_592c_2125fb6cfd5d
  76b5102d_e435_8761_15f1_bd6e6c57d5a3["traverse()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| 76b5102d_e435_8761_15f1_bd6e6c57d5a3
  2a4676b0_3474_8b6b_8cd5_cc83c702bc40["get()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| 2a4676b0_3474_8b6b_8cd5_cc83c702bc40
  ba3e2e94_ad22_f194_419c_8e274feb8fdd["queueWatcher()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| ba3e2e94_ad22_f194_419c_8e274feb8fdd
  eb15026c_5696_e629_0e8f_4bc0a98f7d98["run()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| eb15026c_5696_e629_0e8f_4bc0a98f7d98
  548462f9_f5ae_6335_80f2_a5f5b9fdf922["teardown()"]
  880ea200_f528_af26_3f6f_c77fc2f21647 -->|calls| 548462f9_f5ae_6335_80f2_a5f5b9fdf922
  style 880ea200_f528_af26_3f6f_c77fc2f21647 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

src/v3/apiWatch.ts lines 154–353

function doWatch(
  source: WatchSource | WatchSource[] | WatchEffect | object,
  cb: WatchCallback | null,
  {
    immediate,
    deep,
    flush = 'pre',
    onTrack,
    onTrigger
  }: WatchOptions = emptyObject
): WatchStopHandle {
  if (__DEV__ && !cb) {
    if (immediate !== undefined) {
      warn(
        `watch() "immediate" option is only respected when using the ` +
          `watch(source, callback, options?) signature.`
      )
    }
    if (deep !== undefined) {
      warn(
        `watch() "deep" option is only respected when using the ` +
          `watch(source, callback, options?) signature.`
      )
    }
  }

  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.`
    )
  }

  const instance = currentInstance
  const call = (fn: Function, type: string, args: any[] | null = null) => {
    const res = invokeWithErrorHandling(fn, null, args, instance, type)
    if (deep && res && res.__ob__) res.__ob__.dep.depend()
    return res
  }

  let getter: () => any
  let forceTrigger = false
  let isMultiSource = false

  if (isRef(source)) {
    getter = () => source.value
    forceTrigger = isShallow(source)
  } else if (isReactive(source)) {
    getter = () => {
      ;(source as any).__ob__.dep.depend()
      return source
    }
    deep = true
  } else if (isArray(source)) {
    isMultiSource = true
    forceTrigger = source.some(s => isReactive(s) || isShallow(s))
    getter = () =>
      source.map(s => {
        if (isRef(s)) {
          return s.value
        } else if (isReactive(s)) {
          s.__ob__.dep.depend()
          return traverse(s)
        } else if (isFunction(s)) {
          return call(s, WATCHER_GETTER)
        } else {
          __DEV__ && warnInvalidSource(s)
        }
      })
  } else if (isFunction(source)) {
    if (cb) {
      // getter with cb
      getter = () => call(source, WATCHER_GETTER)
    } else {
      // no cb -> simple effect
      getter = () => {
        if (instance && instance._isDestroyed) {
          return
        }
        if (cleanup) {
          cleanup()
        }
        return call(source, WATCHER, [onCleanup])
      }
    }
  } else {
    getter = noop
    __DEV__ && warnInvalidSource(source)
  }

  if (cb && deep) {
    const baseGetter = getter
    getter = () => traverse(baseGetter())
  }

  let cleanup: () => void
  let onCleanup: OnCleanup = (fn: () => void) => {
    cleanup = watcher.onStop = () => {
      call(fn, WATCHER_CLEANUP)
    }
  }

  // in SSR there is no need to setup an actual effect, and it should be noop
  // unless it's eager
  if (isServerRendering()) {
    // we will also not call the invalidate callback (+ runner is not set up)
    onCleanup = noop
    if (!cb) {
      getter()
    } else if (immediate) {
      call(cb, WATCHER_CB, [
        getter(),
        isMultiSource ? [] : undefined,
        onCleanup
      ])
    }
    return noop
  }

  const watcher = new Watcher(currentInstance, getter, noop, {
    lazy: true
  })
  watcher.noRecurse = !cb

  let oldValue = isMultiSource ? [] : INITIAL_WATCHER_VALUE
  // overwrite default run
  watcher.run = () => {
    if (!watcher.active) {
      return
    }
    if (cb) {
      // watch(source, cb)
      const newValue = watcher.get()
      if (
        deep ||
        forceTrigger ||
        (isMultiSource
          ? (newValue as any[]).some((v, i) =>
              hasChanged(v, (oldValue as any[])[i])
            )
          : hasChanged(newValue, oldValue))
      ) {
        // cleanup before running cb again
        if (cleanup) {
          cleanup()
        }
        call(cb, WATCHER_CB, [
          newValue,
          // pass undefined as the old value when it's changed for the first time
          oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue,
          onCleanup
        ])
        oldValue = newValue
      }
    } else {
      // watchEffect
      watcher.get()
    }
  }

  if (flush === 'sync') {
    watcher.update = watcher.run
  } else if (flush === 'post') {
    watcher.post = true
    watcher.update = () => queueWatcher(watcher)
  } else {
    // pre
    watcher.update = () => {
      if (instance && instance === currentInstance && !instance._isMounted) {
        // pre-watcher triggered before
        const buffer = instance._preWatchers || (instance._preWatchers = [])
        if (buffer.indexOf(watcher) < 0) buffer.push(watcher)
      } else {
        queueWatcher(watcher)
      }
    }
  }

  if (__DEV__) {
    watcher.onTrack = onTrack
    watcher.onTrigger = onTrigger
  }

  // initial run
  if (cb) {
    if (immediate) {
      watcher.run()
    } else {
      oldValue = watcher.get()
    }
  } else if (flush === 'post' && instance) {
    instance.$once('hook:mounted', () => watcher.get())
  } else {
    watcher.get()
  }

  return () => {
    watcher.teardown()
  }
}

Domain

Subdomains

Frequently Asked Questions

What does doWatch() do?
doWatch() is a function in the vue codebase.
What does doWatch() call?
doWatch() calls 10 function(s): depend, get, isReactive, isRef, isShallow, queueWatcher, run, teardown, and 2 more.
What calls doWatch()?
doWatch() is called by 4 function(s): watch, watchEffect, watchPostEffect, watchSyncEffect.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free