@@ -53,6 +53,7 @@ export interface WatchOptionsBase extends DebuggerOptions {
5353export interface WatchOptions < Immediate = boolean > extends WatchOptionsBase {
5454 immediate ?: Immediate
5555 deep ?: boolean
56+ equals ?: ( value : any , oldValue : any ) => boolean
5657}
5758
5859export type WatchStopHandle = ( ) => void
@@ -159,7 +160,8 @@ function doWatch(
159160 deep,
160161 flush = 'pre' ,
161162 onTrack,
162- onTrigger
163+ onTrigger,
164+ equals
163165 } : WatchOptions = emptyObject
164166) : WatchStopHandle {
165167 if ( __DEV__ && ! cb ) {
@@ -175,6 +177,17 @@ function doWatch(
175177 `watch(source, callback, options?) signature.`
176178 )
177179 }
180+ if ( equals !== undefined ) {
181+ warn (
182+ `watch() "equals" option is only respected when using the ` +
183+ `watch(source, callback, options?) signature.`
184+ )
185+ }
186+ }
187+
188+ const equalsFn = isFunction ( equals ) ? equals : undefined
189+ if ( __DEV__ && equals !== undefined && ! equalsFn ) {
190+ warn ( `watch() "equals" option must be a function.` )
178191 }
179192
180193 const warnInvalidSource = ( s : unknown ) => {
@@ -275,7 +288,18 @@ function doWatch(
275288 } )
276289 watcher . noRecurse = ! cb
277290
278- let oldValue = isMultiSource ? [ ] : INITIAL_WATCHER_VALUE
291+ let oldValue : any = INITIAL_WATCHER_VALUE
292+ const hasChangedValue = ( newValue : any , oldValue : any ) => {
293+ if ( equalsFn ) {
294+ return ! equalsFn ( newValue , oldValue )
295+ }
296+ if ( isMultiSource ) {
297+ return ( newValue as any [ ] ) . some ( ( v , i ) =>
298+ hasChanged ( v , ( oldValue as any [ ] ) [ i ] )
299+ )
300+ }
301+ return hasChanged ( newValue , oldValue )
302+ }
279303 // overwrite default run
280304 watcher . run = ( ) => {
281305 if ( ! watcher . active ) {
@@ -284,14 +308,12 @@ function doWatch(
284308 if ( cb ) {
285309 // watch(source, cb)
286310 const newValue = watcher . get ( )
311+ const isInitialValue = oldValue === INITIAL_WATCHER_VALUE
287312 if (
288- deep ||
289- forceTrigger ||
290- ( isMultiSource
291- ? ( newValue as any [ ] ) . some ( ( v , i ) =>
292- hasChanged ( v , ( oldValue as any [ ] ) [ i ] )
293- )
294- : hasChanged ( newValue , oldValue ) )
313+ isInitialValue ||
314+ ( equalsFn
315+ ? hasChangedValue ( newValue , oldValue )
316+ : deep || forceTrigger || hasChangedValue ( newValue , oldValue ) )
295317 ) {
296318 // cleanup before running cb again
297319 if ( cleanup ) {
@@ -300,7 +322,7 @@ function doWatch(
300322 call ( cb , WATCHER_CB , [
301323 newValue ,
302324 // pass undefined as the old value when it's changed for the first time
303- oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue ,
325+ isInitialValue ? ( isMultiSource ? [ ] : undefined ) : oldValue ,
304326 onCleanup
305327 ] )
306328 oldValue = newValue
0 commit comments