fix(runtime-vapor): handle v-model vdom interop error (#13643)

This commit is contained in:
edison 2025-07-18 17:34:50 +08:00 committed by GitHub
parent fca74b00a8
commit 2be828a0c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 68 additions and 3 deletions

View File

@ -2727,7 +2727,7 @@ export function traverseStaticChildren(
function locateNonHydratedAsyncRoot(
instance: ComponentInternalInstance,
): ComponentInternalInstance | undefined {
const subComponent = instance.subTree.component
const subComponent = instance.vapor ? null : instance.subTree.component
if (subComponent) {
if (subComponent.asyncDep && !subComponent.asyncResolved) {
return subComponent

View File

@ -1,6 +1,23 @@
import { createVNode, defineComponent, h, renderSlot } from '@vue/runtime-dom'
import {
createVNode,
defineComponent,
h,
nextTick,
ref,
renderSlot,
toDisplayString,
useModel,
} from '@vue/runtime-dom'
import { makeInteropRender } from './_utils'
import { createComponent, defineVaporComponent } from '../src'
import {
applyTextModel,
child,
createComponent,
defineVaporComponent,
renderEffect,
setText,
template,
} from '../src'
const define = makeInteropRender()
@ -26,6 +43,54 @@ describe('vdomInterop', () => {
})
})
describe('v-model', () => {
test('basic work', async () => {
const VaporChild = defineVaporComponent({
props: {
modelValue: {},
modelModifiers: {},
},
emits: ['update:modelValue'],
setup(__props) {
const modelValue = useModel(__props, 'modelValue')
const n0 = template('<h1> </h1>')() as any
const n1 = template('<input>')() as any
const x0 = child(n0) as any
applyTextModel(
n1,
() => modelValue.value,
_value => (modelValue.value = _value),
)
renderEffect(() => setText(x0, toDisplayString(modelValue.value)))
return [n0, n1]
},
})
const { html, host } = define({
setup() {
const msg = ref('foo')
return () =>
h(VaporChild as any, {
modelValue: msg.value,
'onUpdate:modelValue': (value: string) => {
msg.value = value
},
})
},
}).render()
expect(html()).toBe('<h1>foo</h1><input>')
const inputEl = host.querySelector('input')!
inputEl.value = 'bar'
inputEl.dispatchEvent(new Event('input'))
await nextTick()
expect(html()).toBe('<h1>bar</h1><input>')
})
})
describe('emit', () => {
test('emit from vapor child to vdom parent', () => {
const VaporChild = defineVaporComponent({