4
4
isRef ,
5
5
Ref ,
6
6
ComputedRef ,
7
- ReactiveEffectOptions
7
+ ReactiveEffectOptions ,
8
+ isReactive
8
9
} from '@vue/reactivity'
9
10
import { queueJob } from './scheduler'
10
11
import {
@@ -80,14 +81,7 @@ export function watchEffect(
80
81
// initial value for watchers to trigger on undefined initial values
81
82
const INITIAL_WATCHER_VALUE = { }
82
83
83
- // overload #1: single source + cb
84
- export function watch < T , Immediate extends Readonly < boolean > = false > (
85
- source : WatchSource < T > ,
86
- cb : WatchCallback < T , Immediate extends true ? ( T | undefined ) : T > ,
87
- options ?: WatchOptions < Immediate >
88
- ) : WatchStopHandle
89
-
90
- // overload #2: array of multiple sources + cb
84
+ // overload #1: array of multiple sources + cb
91
85
// Readonly constraint helps the callback to correctly infer value types based
92
86
// on position in the source array. Otherwise the values will get a union type
93
87
// of all possible value types.
@@ -100,6 +94,23 @@ export function watch<
100
94
options ?: WatchOptions < Immediate >
101
95
) : WatchStopHandle
102
96
97
+ // overload #2: single source + cb
98
+ export function watch < T , Immediate extends Readonly < boolean > = false > (
99
+ source : WatchSource < T > ,
100
+ cb : WatchCallback < T , Immediate extends true ? ( T | undefined ) : T > ,
101
+ options ?: WatchOptions < Immediate >
102
+ ) : WatchStopHandle
103
+
104
+ // overload #3: watching reactive object w/ cb
105
+ export function watch <
106
+ T extends object ,
107
+ Immediate extends Readonly < boolean > = false
108
+ > (
109
+ source : T ,
110
+ cb : WatchCallback < T , Immediate extends true ? ( T | undefined ) : T > ,
111
+ options ?: WatchOptions < Immediate >
112
+ ) : WatchStopHandle
113
+
103
114
// implementation
104
115
export function watch < T = any > (
105
116
source : WatchSource < T > | WatchSource < T > [ ] ,
@@ -149,26 +160,39 @@ function doWatch(
149
160
)
150
161
} else if ( isRef ( source ) ) {
151
162
getter = ( ) => source . value
152
- } else if ( cb ) {
153
- // getter with cb
154
- getter = ( ) =>
155
- callWithErrorHandling ( source , instance , ErrorCodes . WATCH_GETTER )
156
- } else {
157
- // no cb -> simple effect
158
- getter = ( ) => {
159
- if ( instance && instance . isUnmounted ) {
160
- return
161
- }
162
- if ( cleanup ) {
163
- cleanup ( )
163
+ } else if ( isReactive ( source ) ) {
164
+ getter = ( ) => source
165
+ deep = true
166
+ } else if ( isFunction ( source ) ) {
167
+ if ( cb ) {
168
+ // getter with cb
169
+ getter = ( ) =>
170
+ callWithErrorHandling ( source , instance , ErrorCodes . WATCH_GETTER )
171
+ } else {
172
+ // no cb -> simple effect
173
+ getter = ( ) => {
174
+ if ( instance && instance . isUnmounted ) {
175
+ return
176
+ }
177
+ if ( cleanup ) {
178
+ cleanup ( )
179
+ }
180
+ return callWithErrorHandling (
181
+ source ,
182
+ instance ,
183
+ ErrorCodes . WATCH_CALLBACK ,
184
+ [ onInvalidate ]
185
+ )
164
186
}
165
- return callWithErrorHandling (
166
- source ,
167
- instance ,
168
- ErrorCodes . WATCH_CALLBACK ,
169
- [ onInvalidate ]
170
- )
171
187
}
188
+ } else {
189
+ getter = NOOP
190
+ warn (
191
+ `Invalid watch source: ` ,
192
+ source ,
193
+ `A watch source can only be a getter/effect function, a ref, ` +
194
+ `a reactive object, or an array of these types.`
195
+ )
172
196
}
173
197
174
198
if ( cb && deep ) {
0 commit comments