From: Evan You Date: Fri, 6 Dec 2024 14:45:45 +0000 (+0800) Subject: wip: slots proxy X-Git-Tag: v3.6.0-alpha.1~16^2~219 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3ef1656d4a9e2b751fe562802efc9ca2da5f3943;p=thirdparty%2Fvuejs%2Fcore.git wip: slots proxy --- diff --git a/packages/runtime-vapor/src/component.ts b/packages/runtime-vapor/src/component.ts index 251ad75bac..79f05c9cd6 100644 --- a/packages/runtime-vapor/src/component.ts +++ b/packages/runtime-vapor/src/component.ts @@ -34,8 +34,8 @@ import { setStyle } from './dom/style' import { setClass, setDynamicProp } from './dom/prop' import { type RawSlots, - type Slot, - getSlotsProxyHandlers, + type StaticSlots, + slotsProxyHandlers, } from './componentSlots' export { currentInstance } from '@vue/runtime-dom' @@ -178,7 +178,7 @@ export class VaporComponentInstance implements GenericComponentInstance { rawProps: RawProps props: Record attrs: Record - slots: Record + slots: StaticSlots exposed: Record | null emitted: Record | null @@ -257,9 +257,7 @@ export class VaporComponentInstance implements GenericComponentInstance { } // init slots - this.slots = rawSlots - ? new Proxy(rawSlots, getSlotsProxyHandlers(comp)) - : EMPTY_OBJ + this.slots = rawSlots ? new Proxy(rawSlots, slotsProxyHandlers) : EMPTY_OBJ if (__DEV__) { // validate props diff --git a/packages/runtime-vapor/src/componentSlots.ts b/packages/runtime-vapor/src/componentSlots.ts new file mode 100644 index 0000000000..a77ade4f3c --- /dev/null +++ b/packages/runtime-vapor/src/componentSlots.ts @@ -0,0 +1,74 @@ +import { NO, hasOwn, isArray, isFunction } from '@vue/shared' +import type { Block } from './block' + +export type RawSlots = Record & { + $?: (StaticSlots | DynamicSlotFn)[] +} + +export type StaticSlots = Record + +export type Slot = (...args: any[]) => Block +export type DynamicSlot = { name: string; fn: Slot } +export type DynamicSlotFn = () => DynamicSlot | DynamicSlot[] + +export const slotsProxyHandlers: ProxyHandler = { + get: getSlot, + has: (target, key: string) => !!getSlot(target, key), + getOwnPropertyDescriptor(target, key: string) { + const slot = getSlot(target, key) + if (slot) { + return { + configurable: true, + enumerable: true, + value: slot, + } + } + }, + ownKeys(target) { + const keys = Object.keys(target) + const dynamicSources = target.$ + if (dynamicSources) { + for (const source of dynamicSources) { + if (isFunction(source)) { + const slot = source() + if (isArray(slot)) { + for (const s of slot) keys.push(s.name) + } else { + keys.push(slot.name) + } + } else { + keys.push(...Object.keys(source)) + } + } + } + return keys + }, + set: NO, + deleteProperty: NO, +} + +function getSlot(target: RawSlots, key: string) { + const dynamicSources = target.$ + if (dynamicSources) { + let i = dynamicSources.length + let source + while (i--) { + source = dynamicSources[i] + if (isFunction(source)) { + const slot = source() + if (isArray(slot)) { + for (const s of slot) { + if (s.name === key) return s.fn + } + } else if (slot.name === key) { + return slot.fn + } + } else if (hasOwn(source, key)) { + return source[key] + } + } + } + if (hasOwn(target, key)) { + return target[key] + } +}