fix(runtime-core): fix async component ref handling (#3191)

fix #3188
This commit is contained in:
HcySunYang 2021-03-02 04:00:32 +08:00 committed by GitHub
parent 3f9906a2f8
commit 7562e72c2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 2 deletions

View File

@ -662,7 +662,7 @@ describe('api: defineAsyncComponent', () => {
})
)
const fooRef = ref()
const fooRef = ref<any>(null)
const toggle = ref(true)
const root = nodeOps.createElement('div')
createApp({
@ -697,4 +697,51 @@ describe('api: defineAsyncComponent', () => {
expect(serializeInner(root)).toBe('resolved')
expect(fooRef.value.id).toBe('foo')
})
// #3188
test('the forwarded template ref should always exist when doing multi patching', async () => {
let resolve: (comp: Component) => void
const Foo = defineAsyncComponent(
() =>
new Promise(r => {
resolve = r as any
})
)
const fooRef = ref<any>(null)
const toggle = ref(true)
const updater = ref(0)
const root = nodeOps.createElement('div')
createApp({
render: () =>
toggle.value ? [h(Foo, { ref: fooRef }), updater.value] : null
}).mount(root)
expect(serializeInner(root)).toBe('<!---->0')
expect(fooRef.value).toBe(null)
resolve!({
data() {
return {
id: 'foo'
}
},
render: () => 'resolved'
})
await timeout()
expect(serializeInner(root)).toBe('resolved0')
expect(fooRef.value.id).toBe('foo')
updater.value++
await nextTick()
expect(serializeInner(root)).toBe('resolved1')
expect(fooRef.value.id).toBe('foo')
toggle.value = false
await nextTick()
expect(serializeInner(root)).toBe('<!---->')
expect(fooRef.value).toBe(null)
})
})

View File

@ -313,9 +313,13 @@ export const setRef = (
}
let value: ComponentPublicInstance | RendererNode | Record<string, any> | null
if (!vnode || isAsyncWrapper(vnode)) {
if (!vnode) {
// means unmount
value = null
} else {
// when mounting async components, nothing needs to be done,
// because the template ref is forwarded to inner component
if (isAsyncWrapper(vnode)) return
if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
value = vnode.component!.exposed || vnode.component!.proxy
} else {