Skip to content

Commit be18b83

Browse files
committed
refactor(runtime-core): replace watch with watchEffect for synchronous and post flush handling
1 parent 748028e commit be18b83

File tree

2 files changed

+19
-30
lines changed

2 files changed

+19
-30
lines changed

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,21 +515,19 @@ describe('api: watch', () => {
515515
source = ref(0)
516516
copyist = ref(0)
517517
// sync flush
518-
watch(
518+
watchEffect(
519519
() => {
520520
const current = (copyist.value = source.value)
521521
onWatcherCleanup(() => calls.push(`sync ${current}`))
522522
},
523-
null,
524523
{ flush: 'sync' },
525524
)
526525
// post flush
527-
watch(
526+
watchEffect(
528527
() => {
529528
const current = copyist.value
530529
onWatcherCleanup(() => calls.push(`post ${current}`))
531530
},
532-
null,
533531
{ flush: 'post' },
534532
)
535533
})

packages/runtime-core/src/apiWatch.ts

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export type MultiWatchSources = (WatchSource<unknown> | object)[]
8888
// overload: single source + cb
8989
export function watch<T, Immediate extends Readonly<boolean> = false>(
9090
source: WatchSource<T>,
91-
cb: WatchCallback<T, MaybeUndefined<T, Immediate>> | null,
91+
cb: WatchCallback<T, MaybeUndefined<T, Immediate>>,
9292
options?: WatchOptions<Immediate>,
9393
): WatchHandle
9494

@@ -98,11 +98,9 @@ export function watch<
9898
Immediate extends Readonly<boolean> = false,
9999
>(
100100
sources: readonly [...T] | T,
101-
cb:
102-
| ([T] extends [ReactiveMarker]
103-
? WatchCallback<T, MaybeUndefined<T, Immediate>>
104-
: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>)
105-
| null,
101+
cb: [T] extends [ReactiveMarker]
102+
? WatchCallback<T, MaybeUndefined<T, Immediate>>
103+
: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
106104
options?: WatchOptions<Immediate>,
107105
): WatchHandle
108106

@@ -112,7 +110,7 @@ export function watch<
112110
Immediate extends Readonly<boolean> = false,
113111
>(
114112
sources: [...T],
115-
cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>> | null,
113+
cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
116114
options?: WatchOptions<Immediate>,
117115
): WatchHandle
118116

@@ -122,17 +120,17 @@ export function watch<
122120
Immediate extends Readonly<boolean> = false,
123121
>(
124122
source: T,
125-
cb: WatchCallback<T, MaybeUndefined<T, Immediate>> | null,
123+
cb: WatchCallback<T, MaybeUndefined<T, Immediate>>,
126124
options?: WatchOptions<Immediate>,
127125
): WatchHandle
128126

129127
// implementation
130128
export function watch<T = any, Immediate extends Readonly<boolean> = false>(
131129
source: T | WatchSource<T>,
132-
cb: WatchCallback | null,
130+
cb: WatchCallback,
133131
options?: WatchOptions<Immediate>,
134132
): WatchHandle {
135-
if (__DEV__ && cb && !isFunction(cb)) {
133+
if (__DEV__ && !isFunction(cb)) {
136134
warn(
137135
`\`watch(fn, options?)\` signature has been moved to a separate API. ` +
138136
`Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` +
@@ -146,20 +144,14 @@ class RenderWatcherEffect extends WatcherEffect {
146144
job: SchedulerJob
147145

148146
constructor(
149-
public instance: GenericComponentInstance | null,
147+
instance: GenericComponentInstance | null,
150148
source: WatchSource | WatchSource[] | WatchEffect | object,
151149
cb: WatchCallback | null,
152150
options: BaseWatchOptions,
153-
public flush: 'pre' | 'post' | 'sync',
151+
private flush: 'pre' | 'post' | 'sync',
154152
) {
155153
super(source, cb, options)
156154

157-
// important: mark the job as a watcher callback so that scheduler knows
158-
// it is allowed to self-trigger (#1727)
159-
if (cb) {
160-
this.flags |= EffectFlags.ALLOW_RECURSE
161-
}
162-
163155
const job: SchedulerJob = () => {
164156
if (this.dirty) {
165157
this.run()
@@ -168,10 +160,11 @@ class RenderWatcherEffect extends WatcherEffect {
168160
// important: mark the job as a watcher callback so that scheduler knows
169161
// it is allowed to self-trigger (#1727)
170162
if (cb) {
163+
this.flags |= EffectFlags.ALLOW_RECURSE
171164
job.flags! |= SchedulerJobFlags.ALLOW_RECURSE
172165
}
173-
if (flush === 'pre' && instance) {
174-
;(job as SchedulerJob).i = instance
166+
if (instance) {
167+
job.i = instance
175168
}
176169
this.job = job
177170
}
@@ -181,13 +174,11 @@ class RenderWatcherEffect extends WatcherEffect {
181174
if (!(flags & EffectFlags.PAUSED)) {
182175
const flush = this.flush
183176
if (flush === 'post') {
184-
queuePostRenderEffect(
185-
this.job,
186-
undefined,
187-
this.instance && this.instance.suspense,
188-
)
177+
const job = this.job
178+
queuePostRenderEffect(job, undefined, job.i ? job.i.suspense : null)
189179
} else if (flush === 'pre') {
190-
queueJob(this.job, this.instance ? this.instance.uid : undefined, true)
180+
const job = this.job
181+
queueJob(job, job.i ? job.i.uid : undefined, true)
191182
} else if (this.dirty) {
192183
this.run()
193184
}

0 commit comments

Comments
 (0)