|
|
@@ -19,11 +19,12 @@ import { isAsyncWrapper } from './apiAsyncComponent'
|
|
|
import { warn } from './warning'
|
|
|
import { isRef, toRaw } from '@vue/reactivity'
|
|
|
import { ErrorCodes, callWithErrorHandling } from './errorHandling'
|
|
|
-import type { SchedulerJob } from './scheduler'
|
|
|
+import { type SchedulerJob, SchedulerJobFlags } from './scheduler'
|
|
|
import { queuePostRenderEffect } from './renderer'
|
|
|
import { type ComponentOptions, getComponentPublicInstance } from './component'
|
|
|
import { knownTemplateRefs } from './helpers/useTemplateRef'
|
|
|
|
|
|
+const pendingSetRefMap = new WeakMap<VNodeNormalizedRef, SchedulerJob>()
|
|
|
/**
|
|
|
* Function for handling a template ref
|
|
|
*/
|
|
|
@@ -106,6 +107,7 @@ export function setRef(
|
|
|
|
|
|
// dynamic ref changed. unset old ref
|
|
|
if (oldRef != null && oldRef !== ref) {
|
|
|
+ invalidatePendingSetRef(oldRawRef!)
|
|
|
if (isString(oldRef)) {
|
|
|
refs[oldRef] = null
|
|
|
if (canSetSetupRef(oldRef)) {
|
|
|
@@ -176,9 +178,15 @@ export function setRef(
|
|
|
// #1789: for non-null values, set them after render
|
|
|
// null values means this is unmount and it should not overwrite another
|
|
|
// ref with the same key
|
|
|
- ;(doSet as SchedulerJob).id = -1
|
|
|
- queuePostRenderEffect(doSet, parentSuspense)
|
|
|
+ const job: SchedulerJob = () => {
|
|
|
+ doSet()
|
|
|
+ pendingSetRefMap.delete(rawRef)
|
|
|
+ }
|
|
|
+ job.id = -1
|
|
|
+ pendingSetRefMap.set(rawRef, job)
|
|
|
+ queuePostRenderEffect(job, parentSuspense)
|
|
|
} else {
|
|
|
+ invalidatePendingSetRef(rawRef)
|
|
|
doSet()
|
|
|
}
|
|
|
} else if (__DEV__) {
|
|
|
@@ -186,3 +194,11 @@ export function setRef(
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+function invalidatePendingSetRef(rawRef: VNodeNormalizedRef) {
|
|
|
+ const pendingSetRef = pendingSetRefMap.get(rawRef)
|
|
|
+ if (pendingSetRef) {
|
|
|
+ pendingSetRef.flags! |= SchedulerJobFlags.DISPOSED
|
|
|
+ pendingSetRefMap.delete(rawRef)
|
|
|
+ }
|
|
|
+}
|