From: zhiyuanzmj <260480378@qq.com> Date: Thu, 10 Jul 2025 01:46:41 +0000 (+0800) Subject: feat(runtime-vapor): support functional slot in vdom component (#13576) X-Git-Tag: v3.6.0-alpha.1~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d5adf95dda31945a227852a6527e25bd91b561c2;p=thirdparty%2Fvuejs%2Fcore.git feat(runtime-vapor): support functional slot in vdom component (#13576) --- diff --git a/packages/runtime-core/src/helpers/renderSlot.ts b/packages/runtime-core/src/helpers/renderSlot.ts index 152c5a4b81..d5feae617a 100644 --- a/packages/runtime-core/src/helpers/renderSlot.ts +++ b/packages/runtime-core/src/helpers/renderSlot.ts @@ -35,7 +35,7 @@ export function renderSlot( let slot = slots[name] // vapor slots rendered in vdom - if (slot && slots._vapor) { + if (slot && (slot as any).__vapor) { const ret = (openBlock(), createBlock(VaporSlot, props)) ret.vs = { slot, fallback } return ret diff --git a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts index 08326d4d5d..582e67dd87 100644 --- a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts +++ b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts @@ -1,4 +1,4 @@ -import { defineComponent, h } from '@vue/runtime-dom' +import { createVNode, defineComponent, h, renderSlot } from '@vue/runtime-dom' import { makeInteropRender } from './_utils' import { createComponent, defineVaporComponent } from '../src' @@ -9,7 +9,65 @@ describe('vdomInterop', () => { describe.todo('emit', () => {}) - describe.todo('slots', () => {}) + describe('slots', () => { + test('basic', () => { + const VDomChild = defineComponent({ + setup(_, { slots }) { + return () => renderSlot(slots, 'default') + }, + }) + + const VaporChild = defineVaporComponent({ + setup() { + return createComponent( + VDomChild as any, + null, + { + default: () => document.createTextNode('default slot'), + }, + true, + ) + }, + }) + + const { html } = define({ + setup() { + return () => h(VaporChild as any) + }, + }).render() + + expect(html()).toBe('default slot') + }) + + test('functional slot', () => { + const VDomChild = defineComponent({ + setup(_, { slots }) { + return () => createVNode(slots.default!) + }, + }) + + const VaporChild = defineVaporComponent({ + setup() { + return createComponent( + VDomChild as any, + null, + { + default: () => document.createTextNode('default slot'), + }, + true, + ) + }, + }) + + const { html } = define({ + setup() { + return () => h(VaporChild as any) + }, + }).render() + + expect(html()).toBe('default slot') + }) + }) describe.todo('provide', () => {}) diff --git a/packages/runtime-vapor/src/componentProps.ts b/packages/runtime-vapor/src/componentProps.ts index 7ee99b6817..b870a21b2e 100644 --- a/packages/runtime-vapor/src/componentProps.ts +++ b/packages/runtime-vapor/src/componentProps.ts @@ -185,7 +185,7 @@ export function getAttrFromRawProps(rawProps: RawProps, key: string): unknown { source = dynamicSources[i] isDynamic = isFunction(source) source = isDynamic ? (source as Function)() : source - if (hasOwn(source, key)) { + if (source && hasOwn(source, key)) { const value = isDynamic ? source[key] : source[key]() if (merged) { merged.push(value) diff --git a/packages/runtime-vapor/src/vdomInterop.ts b/packages/runtime-vapor/src/vdomInterop.ts index e277024d73..8c1dd2cee2 100644 --- a/packages/runtime-vapor/src/vdomInterop.ts +++ b/packages/runtime-vapor/src/vdomInterop.ts @@ -134,11 +134,11 @@ const vaporSlotPropsProxyHandler: ProxyHandler< const vaporSlotsProxyHandler: ProxyHandler = { get(target, key) { - if (key === '_vapor') { - return target - } else { - return target[key] + const slot = target[key] + if (isFunction(slot)) { + slot.__vapor = true } + return slot }, }