From: edison Date: Fri, 18 Jul 2025 09:34:50 +0000 (+0800) Subject: fix(runtime-vapor): handle v-model vdom interop error (#13643) X-Git-Tag: v3.6.0-alpha.2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2be828a0c165c7f1533ace0bd81fba43a2af16d6;p=thirdparty%2Fvuejs%2Fcore.git fix(runtime-vapor): handle v-model vdom interop error (#13643) --- diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index bad40f1439..30f9e6b2c1 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -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 diff --git a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts index 96222e6ee0..98c4cdbc9d 100644 --- a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts +++ b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts @@ -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('

')() as any + const n1 = template('')() 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('

foo

') + + const inputEl = host.querySelector('input')! + inputEl.value = 'bar' + inputEl.dispatchEvent(new Event('input')) + + await nextTick() + expect(html()).toBe('

bar

') + }) + }) + describe('emit', () => { test('emit from vapor child to vdom parent', () => { const VaporChild = defineVaporComponent({