mirror of https://github.com/vuejs/core.git
fix(templateRef): add support for dynamic components
This commit is contained in:
parent
9ab8e4c0c9
commit
305a0e8b89
|
@ -1,10 +1,13 @@
|
|||
import type { NodeRef } from '../../src/apiTemplateRef'
|
||||
import {
|
||||
child,
|
||||
createComponent,
|
||||
createDynamicComponent,
|
||||
createFor,
|
||||
createIf,
|
||||
createSlot,
|
||||
createTemplateRefSetter,
|
||||
defineVaporComponent,
|
||||
insert,
|
||||
renderEffect,
|
||||
template,
|
||||
|
@ -19,7 +22,8 @@ import {
|
|||
useTemplateRef,
|
||||
watchEffect,
|
||||
} from '@vue/runtime-dom'
|
||||
import { setElementText } from '../../src/dom/prop'
|
||||
import { setElementText, setText } from '../../src/dom/prop'
|
||||
import type { VaporComponent } from '../../src/component'
|
||||
|
||||
const define = makeRender()
|
||||
|
||||
|
@ -676,6 +680,39 @@ describe('api: template ref', () => {
|
|||
expect(r!.value).toBe(n)
|
||||
})
|
||||
|
||||
test('work with dynamic component', async () => {
|
||||
const Child = defineVaporComponent({
|
||||
setup(_, { expose }) {
|
||||
const msg = ref('one')
|
||||
expose({ setMsg: (m: string) => (msg.value = m) })
|
||||
const n0 = template(`<div> </div>`)() as any
|
||||
const x0 = child(n0) as any
|
||||
renderEffect(() => setText(x0, msg.value))
|
||||
return n0
|
||||
},
|
||||
})
|
||||
|
||||
const views: Record<string, VaporComponent> = { child: Child }
|
||||
const view = ref('child')
|
||||
const refKey = ref<InstanceType<any>>(null)
|
||||
|
||||
const { html } = define({
|
||||
setup() {
|
||||
const setRef = createTemplateRefSetter()
|
||||
const n0 = createDynamicComponent(() => views[view.value]) as any
|
||||
setRef(n0, refKey)
|
||||
return n0
|
||||
},
|
||||
}).render()
|
||||
|
||||
expect(html()).toBe('<div>one</div><!--dynamic-component-->')
|
||||
expect(refKey.value).toBeDefined()
|
||||
|
||||
refKey.value.setMsg('changed')
|
||||
await nextTick()
|
||||
expect(html()).toBe('<div>changed</div><!--dynamic-component-->')
|
||||
})
|
||||
|
||||
// TODO: can not reproduce in Vapor
|
||||
// // #2078
|
||||
// test('handling multiple merged refs', async () => {
|
||||
|
|
|
@ -20,6 +20,7 @@ import {
|
|||
isString,
|
||||
remove,
|
||||
} from '@vue/shared'
|
||||
import { DynamicFragment } from './block'
|
||||
|
||||
export type NodeRef = string | Ref | ((ref: Element) => void)
|
||||
export type RefEl = Element | VaporComponentInstance
|
||||
|
@ -49,7 +50,7 @@ export function setRef(
|
|||
if (!instance || instance.isUnmounted) return
|
||||
|
||||
const setupState: any = __DEV__ ? instance.setupState || {} : null
|
||||
const refValue = isVaporComponent(el) ? getExposed(el) || el : el
|
||||
const refValue = getRefValue(el)
|
||||
|
||||
const refs =
|
||||
instance.refs === EMPTY_OBJ ? (instance.refs = {}) : instance.refs
|
||||
|
@ -143,3 +144,12 @@ export function setRef(
|
|||
}
|
||||
return ref
|
||||
}
|
||||
|
||||
const getRefValue = (el: RefEl) => {
|
||||
if (isVaporComponent(el)) {
|
||||
return getExposed(el) || el
|
||||
} else if (el instanceof DynamicFragment) {
|
||||
return getRefValue(el.nodes as RefEl)
|
||||
}
|
||||
return el
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue