fix(runtime-core/scheduler): avoid duplicate updates of child component
This commit is contained in:
parent
778f3a5e88
commit
8a87074df0
@ -1,4 +1,9 @@
|
||||
import { queueJob, nextTick, queuePostFlushCb } from '../src/scheduler'
|
||||
import {
|
||||
queueJob,
|
||||
nextTick,
|
||||
queuePostFlushCb,
|
||||
invalidateJob
|
||||
} from '../src/scheduler'
|
||||
|
||||
describe('scheduler', () => {
|
||||
it('nextTick', async () => {
|
||||
@ -230,4 +235,23 @@ describe('scheduler', () => {
|
||||
expect(calls).toEqual(['job1', 'job2', 'cb1', 'cb2'])
|
||||
})
|
||||
})
|
||||
|
||||
test('invalidateJob', async () => {
|
||||
const calls: string[] = []
|
||||
const job1 = () => {
|
||||
calls.push('job1')
|
||||
invalidateJob(job2)
|
||||
job2()
|
||||
}
|
||||
const job2 = () => {
|
||||
calls.push('job2')
|
||||
}
|
||||
// queue both jobs
|
||||
queueJob(job1)
|
||||
queueJob(job2)
|
||||
expect(calls).toEqual([])
|
||||
await nextTick()
|
||||
// job2 should be called only once
|
||||
expect(calls).toEqual(['job1', 'job2'])
|
||||
})
|
||||
})
|
||||
|
@ -30,7 +30,12 @@ import {
|
||||
isFunction,
|
||||
PatchFlags
|
||||
} from '@vue/shared'
|
||||
import { queueJob, queuePostFlushCb, flushPostFlushCbs } from './scheduler'
|
||||
import {
|
||||
queueJob,
|
||||
queuePostFlushCb,
|
||||
flushPostFlushCbs,
|
||||
invalidateJob
|
||||
} from './scheduler'
|
||||
import {
|
||||
effect,
|
||||
stop,
|
||||
@ -895,6 +900,9 @@ export function createRenderer<
|
||||
} else {
|
||||
// normal update
|
||||
instance.next = n2
|
||||
// in case the child component is also queued, remove it to avoid
|
||||
// double updating the same child component in the same flush.
|
||||
invalidateJob(instance.update)
|
||||
// instance.update is the reactive effect runner.
|
||||
instance.update()
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ErrorCodes, callWithErrorHandling } from './errorHandling'
|
||||
import { isArray } from '@vue/shared'
|
||||
|
||||
const queue: Function[] = []
|
||||
const queue: (Function | null)[] = []
|
||||
const postFlushCbs: Function[] = []
|
||||
const p = Promise.resolve()
|
||||
|
||||
@ -22,6 +22,13 @@ export function queueJob(job: () => void) {
|
||||
}
|
||||
}
|
||||
|
||||
export function invalidateJob(job: () => void) {
|
||||
const i = queue.indexOf(job)
|
||||
if (i > -1) {
|
||||
queue[i] = null
|
||||
}
|
||||
}
|
||||
|
||||
export function queuePostFlushCb(cb: Function | Function[]) {
|
||||
if (!isArray(cb)) {
|
||||
postFlushCbs.push(cb)
|
||||
@ -64,6 +71,9 @@ function flushJobs(seen?: CountMap) {
|
||||
seen = seen || new Map()
|
||||
}
|
||||
while ((job = queue.shift())) {
|
||||
if (job === null) {
|
||||
continue
|
||||
}
|
||||
if (__DEV__) {
|
||||
checkRecursiveUpdates(seen!, job)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user