Skip to content

Commit 24d77c2

Browse files
committed
perf(watch): avoid double traverse for reactive source
1 parent 8f85b6d commit 24d77c2

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

packages/runtime-core/__tests__/apiWatch.spec.ts

+18
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,24 @@ describe('api: watch', () => {
211211
expect(cb).toBeCalledTimes(1)
212212
})
213213

214+
it('should still respect deep: true on shallowReactive source', async () => {
215+
const obj = reactive({ a: 1 })
216+
const arr = shallowReactive([obj])
217+
218+
let dummy
219+
watch(
220+
arr,
221+
() => {
222+
dummy = arr[0].a
223+
},
224+
{ deep: true },
225+
)
226+
227+
obj.a++
228+
await nextTick()
229+
expect(dummy).toBe(2)
230+
})
231+
214232
it('watching multiple sources', async () => {
215233
const state = reactive({ count: 1 })
216234
const count = ref(1)

packages/runtime-core/src/apiWatch.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,12 @@ function doWatch(
222222

223223
const instance =
224224
getCurrentScope() === currentInstance?.scope ? currentInstance : null
225-
// const instance = currentInstance
225+
const reactiveGetter = (source: object) =>
226+
deep === true
227+
? source // traverse will happen in wrapped getter below
228+
: // for shallow or deep: false, only traverse root-level properties
229+
traverse(source, isShallow(source) || deep === false ? 1 : undefined)
230+
226231
let getter: () => any
227232
let forceTrigger = false
228233
let isMultiSource = false
@@ -231,10 +236,7 @@ function doWatch(
231236
getter = () => source.value
232237
forceTrigger = isShallow(source)
233238
} else if (isReactive(source)) {
234-
getter =
235-
isShallow(source) || deep === false
236-
? () => traverse(source, 1)
237-
: () => traverse(source)
239+
getter = () => reactiveGetter(source)
238240
forceTrigger = true
239241
} else if (isArray(source)) {
240242
isMultiSource = true
@@ -244,7 +246,7 @@ function doWatch(
244246
if (isRef(s)) {
245247
return s.value
246248
} else if (isReactive(s)) {
247-
return traverse(s, isShallow(s) || deep === false ? 1 : undefined)
249+
return reactiveGetter(s)
248250
} else if (isFunction(s)) {
249251
return callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER)
250252
} else {

0 commit comments

Comments
 (0)