From 4dbcd259dc36c897e968e82febdd8ee75478a5c6 Mon Sep 17 00:00:00 2001 From: zhiyuanzmj <260480378@qq.com> Date: Sat, 19 Jul 2025 10:07:08 +0800 Subject: [PATCH 1/2] fix(runtime-vapor): add __vapor flag for dynamic component --- packages/runtime-vapor/src/apiCreateDynamicComponent.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/runtime-vapor/src/apiCreateDynamicComponent.ts b/packages/runtime-vapor/src/apiCreateDynamicComponent.ts index 945e0f38d87..208e0ca4120 100644 --- a/packages/runtime-vapor/src/apiCreateDynamicComponent.ts +++ b/packages/runtime-vapor/src/apiCreateDynamicComponent.ts @@ -1,4 +1,4 @@ -import { resolveDynamicComponent } from '@vue/runtime-dom' +import { currentInstance, resolveDynamicComponent } from '@vue/runtime-dom' import { DynamicFragment, type VaporFragment, insert } from './block' import { createComponentWithFallback } from './component' import { renderEffect } from './renderEffect' @@ -31,6 +31,9 @@ export function createDynamicComponent( renderEffect(() => { const value = getter() + if (currentInstance && currentInstance.appContext.vapor) { + value.__vapor = true + } frag.update( () => createComponentWithFallback( From dca0639e79b017746a1f34777539eba19b6cbade Mon Sep 17 00:00:00 2001 From: zhiyuanzmj <260480378@qq.com> Date: Sat, 19 Jul 2025 10:50:14 +0800 Subject: [PATCH 2/2] chore: add test --- packages/runtime-vapor/__tests__/_utils.ts | 64 +++++++++++-------- .../__tests__/vdomInterop.spec.ts | 21 +++++- 2 files changed, 55 insertions(+), 30 deletions(-) diff --git a/packages/runtime-vapor/__tests__/_utils.ts b/packages/runtime-vapor/__tests__/_utils.ts index d1ede2a6c9a..c5000f5e644 100644 --- a/packages/runtime-vapor/__tests__/_utils.ts +++ b/packages/runtime-vapor/__tests__/_utils.ts @@ -93,7 +93,10 @@ export interface InteropRenderContext { html: () => string } -export function makeInteropRender(): (comp: Component) => InteropRenderContext { +export function makeInteropRender(): { + define: (comp: Component) => InteropRenderContext + defineVapor: (comp: VaporComponent) => InteropRenderContext +} { let host: HTMLElement beforeEach(() => { host = document.createElement('div') @@ -102,36 +105,41 @@ export function makeInteropRender(): (comp: Component) => InteropRenderContext { host.remove() }) - function define(comp: Component) { - let app: App - function render( - props: RawProps | undefined = undefined, - container: string | ParentNode = host, - ) { - app?.unmount() - app = createApp(comp, props) - app.use(vaporInteropPlugin) - return mount(container) - } + const defineFactory = + (createAppFactory: typeof createApp | typeof createVaporApp) => + (comp: Component | VaporComponent) => { + let app: App + function render( + props: RawProps | undefined = undefined, + container: string | ParentNode = host, + ) { + app?.unmount() + app = createAppFactory(comp as any, props) + app.use(vaporInteropPlugin) + return mount(container) + } + + function mount(container: string | ParentNode = host) { + app.mount(container) + return res() + } + + function html() { + return host.innerHTML + } + + const res = () => ({ + host, + mount, + render, + html, + }) - function mount(container: string | ParentNode = host) { - app.mount(container) return res() } - function html() { - return host.innerHTML - } - - const res = () => ({ - host, - mount, - render, - html, - }) - - return res() + return { + define: defineFactory(createApp), + defineVapor: defineFactory(createVaporApp), } - - return define } diff --git a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts index 98c4cdbc9d0..50f8a478855 100644 --- a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts +++ b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts @@ -13,13 +13,14 @@ import { applyTextModel, child, createComponent, + createDynamicComponent, defineVaporComponent, renderEffect, setText, template, } from '../src' -const define = makeInteropRender() +const { define, defineVapor } = makeInteropRender() describe('vdomInterop', () => { describe('props', () => { @@ -179,7 +180,23 @@ describe('vdomInterop', () => { describe.todo('template ref', () => {}) - describe.todo('dynamic component', () => {}) + describe('dynamic component', () => { + it('should not render to Virtual DOM', () => { + const VaporChild = defineVaporComponent({ + setup() { + return createDynamicComponent( + () => () => document.createTextNode('foo'), + ) + }, + }) + + const { host } = defineVapor(VaporChild).render() + + expect(host.innerHTML).toMatchInlineSnapshot( + `"foo"`, + ) + }) + }) describe('attribute fallthrough', () => { it('should not fallthrough emit handlers to vdom child', () => {