mirror of https://github.com/vuejs/core.git
Merge f826689846
into ba391f5fdf
This commit is contained in:
commit
d6eb901616
|
@ -10,6 +10,7 @@ import {
|
|||
render,
|
||||
serializeInner,
|
||||
shallowRef,
|
||||
watch,
|
||||
} from '@vue/runtime-test'
|
||||
|
||||
describe('api: template refs', () => {
|
||||
|
@ -179,6 +180,89 @@ describe('api: template refs', () => {
|
|||
expect(el.value).toBe(null)
|
||||
})
|
||||
|
||||
// #12639
|
||||
it('update and unmount child in the same tick', async () => {
|
||||
const root = nodeOps.createElement('div')
|
||||
const el = ref(null)
|
||||
const toggle = ref(true)
|
||||
const show = ref(true)
|
||||
|
||||
const Comp = defineComponent({
|
||||
emits: ['change'],
|
||||
props: ['show'],
|
||||
setup(props, { emit }) {
|
||||
watch(
|
||||
() => props.show,
|
||||
() => {
|
||||
emit('change')
|
||||
},
|
||||
)
|
||||
return () => h('div', 'hi')
|
||||
},
|
||||
})
|
||||
|
||||
const App = {
|
||||
setup() {
|
||||
return {
|
||||
refKey: el,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
return toggle.value
|
||||
? h(Comp, {
|
||||
ref: 'refKey',
|
||||
show: show.value,
|
||||
onChange: () => (toggle.value = false),
|
||||
})
|
||||
: null
|
||||
},
|
||||
}
|
||||
render(h(App), root)
|
||||
expect(el.value).not.toBe(null)
|
||||
|
||||
show.value = false
|
||||
await nextTick()
|
||||
expect(el.value).toBe(null)
|
||||
})
|
||||
|
||||
it('set and change ref in the same tick', async () => {
|
||||
const root = nodeOps.createElement('div')
|
||||
const show = ref(false)
|
||||
const refName = ref('a')
|
||||
|
||||
const Child = defineComponent({
|
||||
setup() {
|
||||
refName.value = 'b'
|
||||
return () => {}
|
||||
},
|
||||
})
|
||||
|
||||
const Comp = {
|
||||
render() {
|
||||
return h(Child, {
|
||||
ref: refName.value,
|
||||
})
|
||||
},
|
||||
updated(this: any) {
|
||||
expect(this.$refs.a).toBe(null)
|
||||
expect(this.$refs.b).not.toBe(null)
|
||||
},
|
||||
}
|
||||
|
||||
const App = {
|
||||
render() {
|
||||
return show.value ? h(Comp) : null
|
||||
},
|
||||
}
|
||||
|
||||
render(h(App), root)
|
||||
expect(refName.value).toBe('a')
|
||||
|
||||
show.value = true
|
||||
await nextTick()
|
||||
expect(refName.value).toBe('b')
|
||||
})
|
||||
|
||||
it('unset old ref when new ref is absent', async () => {
|
||||
const root1 = nodeOps.createElement('div')
|
||||
const root2 = nodeOps.createElement('div')
|
||||
|
|
|
@ -13,11 +13,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
|
||||
*/
|
||||
|
@ -96,6 +97,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)) {
|
||||
|
@ -153,9 +155,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__) {
|
||||
|
@ -163,3 +171,11 @@ export function setRef(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function invalidatePendingSetRef(rawRef: VNodeNormalizedRef) {
|
||||
const pendingSetRef = pendingSetRefMap.get(rawRef)
|
||||
if (pendingSetRef) {
|
||||
pendingSetRef.flags! |= SchedulerJobFlags.DISPOSED
|
||||
pendingSetRefMap.delete(rawRef)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue