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 type { NodeRef } from '../../src/apiTemplateRef'
|
||||||
import {
|
import {
|
||||||
|
child,
|
||||||
createComponent,
|
createComponent,
|
||||||
|
createDynamicComponent,
|
||||||
createFor,
|
createFor,
|
||||||
createIf,
|
createIf,
|
||||||
createSlot,
|
createSlot,
|
||||||
createTemplateRefSetter,
|
createTemplateRefSetter,
|
||||||
|
defineVaporComponent,
|
||||||
insert,
|
insert,
|
||||||
renderEffect,
|
renderEffect,
|
||||||
template,
|
template,
|
||||||
|
@ -19,7 +22,8 @@ import {
|
||||||
useTemplateRef,
|
useTemplateRef,
|
||||||
watchEffect,
|
watchEffect,
|
||||||
} from '@vue/runtime-dom'
|
} 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()
|
const define = makeRender()
|
||||||
|
|
||||||
|
@ -676,6 +680,39 @@ describe('api: template ref', () => {
|
||||||
expect(r!.value).toBe(n)
|
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
|
// TODO: can not reproduce in Vapor
|
||||||
// // #2078
|
// // #2078
|
||||||
// test('handling multiple merged refs', async () => {
|
// test('handling multiple merged refs', async () => {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
isString,
|
isString,
|
||||||
remove,
|
remove,
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
|
import { DynamicFragment } from './block'
|
||||||
|
|
||||||
export type NodeRef = string | Ref | ((ref: Element) => void)
|
export type NodeRef = string | Ref | ((ref: Element) => void)
|
||||||
export type RefEl = Element | VaporComponentInstance
|
export type RefEl = Element | VaporComponentInstance
|
||||||
|
@ -49,7 +50,7 @@ export function setRef(
|
||||||
if (!instance || instance.isUnmounted) return
|
if (!instance || instance.isUnmounted) return
|
||||||
|
|
||||||
const setupState: any = __DEV__ ? instance.setupState || {} : null
|
const setupState: any = __DEV__ ? instance.setupState || {} : null
|
||||||
const refValue = isVaporComponent(el) ? getExposed(el) || el : el
|
const refValue = getRefValue(el)
|
||||||
|
|
||||||
const refs =
|
const refs =
|
||||||
instance.refs === EMPTY_OBJ ? (instance.refs = {}) : instance.refs
|
instance.refs === EMPTY_OBJ ? (instance.refs = {}) : instance.refs
|
||||||
|
@ -143,3 +144,12 @@ export function setRef(
|
||||||
}
|
}
|
||||||
return ref
|
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