| 118 | } |
| 119 | |
| 120 | export function watch( |
| 121 | source: WatchSource | WatchSource[] | WatchEffect | object, |
| 122 | cb?: WatchCallback | null, |
| 123 | options: WatchOptions = EMPTY_OBJ, |
| 124 | ): WatchHandle { |
| 125 | const { immediate, deep, once, scheduler, augmentJob, call } = options |
| 126 | |
| 127 | const warnInvalidSource = (s: unknown) => { |
| 128 | ;(options.onWarn || warn)( |
| 129 | `Invalid watch source: `, |
| 130 | s, |
| 131 | `A watch source can only be a getter/effect function, a ref, ` + |
| 132 | `a reactive object, or an array of these types.`, |
| 133 | ) |
| 134 | } |
| 135 | |
| 136 | const reactiveGetter = (source: object) => { |
| 137 | // traverse will happen in wrapped getter below |
| 138 | if (deep) return source |
| 139 | // for `deep: false | 0` or shallow reactive, only traverse root-level properties |
| 140 | if (isShallow(source) || deep === false || deep === 0) |
| 141 | return traverse(source, 1) |
| 142 | // for `deep: undefined` on a reactive object, deeply traverse all properties |
| 143 | return traverse(source) |
| 144 | } |
| 145 | |
| 146 | let effect: ReactiveEffect |
| 147 | let getter: () => any |
| 148 | let cleanup: (() => void) | undefined |
| 149 | let boundCleanup: typeof onWatcherCleanup |
| 150 | let forceTrigger = false |
| 151 | let isMultiSource = false |
| 152 | |
| 153 | if (isRef(source)) { |
| 154 | getter = () => source.value |
| 155 | forceTrigger = isShallow(source) |
| 156 | } else if (isReactive(source)) { |
| 157 | getter = () => reactiveGetter(source) |
| 158 | forceTrigger = true |
| 159 | } else if (isArray(source)) { |
| 160 | isMultiSource = true |
| 161 | forceTrigger = source.some(s => isReactive(s) || isShallow(s)) |
| 162 | getter = () => |
| 163 | source.map(s => { |
| 164 | if (isRef(s)) { |
| 165 | return s.value |
| 166 | } else if (isReactive(s)) { |
| 167 | return reactiveGetter(s) |
| 168 | } else if (isFunction(s)) { |
| 169 | return call ? call(s, WatchErrorCodes.WATCH_GETTER) : s() |
| 170 | } else { |
| 171 | __DEV__ && warnInvalidSource(s) |
| 172 | } |
| 173 | }) |
| 174 | } else if (isFunction(source)) { |
| 175 | if (cb) { |
| 176 | // getter with cb |
| 177 | getter = call |