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 CoreInstance VDOM calls 10 called by 4

Entity Profile

Dependency Diagram

graph TD
  b2856354_51ef_6ef1_ec4b_ae2e72186601["doWatch()"]
  0bfbb910_39a9_6fb2_a13f_4bd26024d513["watchEffect()"]
  0bfbb910_39a9_6fb2_a13f_4bd26024d513 -->|calls| b2856354_51ef_6ef1_ec4b_ae2e72186601
  8c4927dd_5736_4f48_c149_40b7d44316c9["watchPostEffect()"]
  8c4927dd_5736_4f48_c149_40b7d44316c9 -->|calls| b2856354_51ef_6ef1_ec4b_ae2e72186601
  3430a392_62b0_9796_2cea_f117f44bb539["watchSyncEffect()"]
  3430a392_62b0_9796_2cea_f117f44bb539 -->|calls| b2856354_51ef_6ef1_ec4b_ae2e72186601
  3cbf8aba_5563_0e8d_9c9d_e4f8166bfefb["watch()"]
  3cbf8aba_5563_0e8d_9c9d_e4f8166bfefb -->|calls| b2856354_51ef_6ef1_ec4b_ae2e72186601
  3cbf8aba_5563_0e8d_9c9d_e4f8166bfefb["watch()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| 3cbf8aba_5563_0e8d_9c9d_e4f8166bfefb
  d1eb6d83_f4fb_7e95_6bf0_bea3d8b0996f["depend()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| d1eb6d83_f4fb_7e95_6bf0_bea3d8b0996f
  1cb75796_39e2_4190_8602_3712ff6cf2f7["isRef()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| 1cb75796_39e2_4190_8602_3712ff6cf2f7
  a641b7eb_3a6c_54f5_9c98_7b09f54970d3["isShallow()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| a641b7eb_3a6c_54f5_9c98_7b09f54970d3
  c5c37a47_bc5f_b7a2_7788_aa7ab748702f["isReactive()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| c5c37a47_bc5f_b7a2_7788_aa7ab748702f
  a1748d17_4487_c7f1_cd6f_4b967a12f725["traverse()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| a1748d17_4487_c7f1_cd6f_4b967a12f725
  c595e491_455c_5f96_1a90_ed59c627158b["get()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| c595e491_455c_5f96_1a90_ed59c627158b
  a5f84bab_9034_ce7b_6911_25c506039541["queueWatcher()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| a5f84bab_9034_ce7b_6911_25c506039541
  df67762e_53ee_05bf_1358_c48dd0fc8f8d["run()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| df67762e_53ee_05bf_1358_c48dd0fc8f8d
  3d03878c_4a3a_4d94_b9f5_3c7287192b05["teardown()"]
  b2856354_51ef_6ef1_ec4b_ae2e72186601 -->|calls| 3d03878c_4a3a_4d94_b9f5_3c7287192b05
  style b2856354_51ef_6ef1_ec4b_ae2e72186601 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