Skip to content

Commit e5a5957

Browse files
authored
fix(runtime-vapor): set ref on dynamic component (#13172)
1 parent ffb7ba7 commit e5a5957

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

packages/runtime-vapor/__tests__/dom/templateRef.spec.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import type { NodeRef } from '../../src/apiTemplateRef'
22
import {
3+
child,
34
createComponent,
5+
createDynamicComponent,
46
createFor,
57
createIf,
68
createSlot,
79
createTemplateRefSetter,
10+
defineVaporComponent,
811
insert,
912
renderEffect,
1013
template,
@@ -19,7 +22,8 @@ import {
1922
useTemplateRef,
2023
watchEffect,
2124
} from '@vue/runtime-dom'
22-
import { setElementText } from '../../src/dom/prop'
25+
import { setElementText, setText } from '../../src/dom/prop'
26+
import type { VaporComponent } from '../../src/component'
2327

2428
const define = makeRender()
2529

@@ -676,6 +680,39 @@ describe('api: template ref', () => {
676680
expect(r!.value).toBe(n)
677681
})
678682

683+
test('work with dynamic component', async () => {
684+
const Child = defineVaporComponent({
685+
setup(_, { expose }) {
686+
const msg = ref('one')
687+
expose({ setMsg: (m: string) => (msg.value = m) })
688+
const n0 = template(`<div> </div>`)() as any
689+
const x0 = child(n0) as any
690+
renderEffect(() => setText(x0, msg.value))
691+
return n0
692+
},
693+
})
694+
695+
const views: Record<string, VaporComponent> = { child: Child }
696+
const view = ref('child')
697+
const refKey = ref<any>(null)
698+
699+
const { html } = define({
700+
setup() {
701+
const setRef = createTemplateRefSetter()
702+
const n0 = createDynamicComponent(() => views[view.value]) as any
703+
setRef(n0, refKey)
704+
return n0
705+
},
706+
}).render()
707+
708+
expect(html()).toBe('<div>one</div><!--dynamic-component-->')
709+
expect(refKey.value).toBeDefined()
710+
711+
refKey.value.setMsg('changed')
712+
await nextTick()
713+
expect(html()).toBe('<div>changed</div><!--dynamic-component-->')
714+
})
715+
679716
// TODO: can not reproduce in Vapor
680717
// // #2078
681718
// test('handling multiple merged refs', async () => {

packages/runtime-vapor/src/apiTemplateRef.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
isString,
2121
remove,
2222
} from '@vue/shared'
23+
import { DynamicFragment } from './block'
2324

2425
export type NodeRef = string | Ref | ((ref: Element) => void)
2526
export type RefEl = Element | VaporComponentInstance
@@ -49,7 +50,7 @@ export function setRef(
4950
if (!instance || instance.isUnmounted) return
5051

5152
const setupState: any = __DEV__ ? instance.setupState || {} : null
52-
const refValue = isVaporComponent(el) ? getExposed(el) || el : el
53+
const refValue = getRefValue(el)
5354

5455
const refs =
5556
instance.refs === EMPTY_OBJ ? (instance.refs = {}) : instance.refs
@@ -143,3 +144,12 @@ export function setRef(
143144
}
144145
return ref
145146
}
147+
148+
const getRefValue = (el: RefEl) => {
149+
if (isVaporComponent(el)) {
150+
return getExposed(el) || el
151+
} else if (el instanceof DynamicFragment) {
152+
return getRefValue(el.nodes as RefEl)
153+
}
154+
return el
155+
}

0 commit comments

Comments
 (0)