]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: component with fallback
authorEvan You <evan@vuejs.org>
Fri, 6 Dec 2024 03:10:35 +0000 (11:10 +0800)
committerEvan You <evan@vuejs.org>
Fri, 6 Dec 2024 03:10:35 +0000 (11:10 +0800)
packages/compiler-vapor/src/generators/component.ts
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/componentProps.ts
packages/runtime-vapor/src/index.ts

index 00ee4df85e33977249c9280d25ae4abf8e049f19..b6e2c621362f4fa61467ed6fa5b25b04b8097665 100644 (file)
@@ -54,7 +54,9 @@ export function genCreateComponent(
     NEWLINE,
     `const n${operation.id} = `,
     ...genCall(
-      vaporHelper('createComponent'),
+      operation.asset
+        ? vaporHelper('createComponentWithFallback')
+        : vaporHelper('createComponent'),
       tag,
       rawProps,
       rawSlots,
index aeaa07164d22f22bf057c0574e8708ea44022264..40290a080f5ff2bb78c3b58c87b0cbc23a826e39 100644 (file)
@@ -19,17 +19,19 @@ import {
 } from '@vue/runtime-dom'
 import { type Block, isBlock } from './block'
 import { pauseTracking, resetTracking } from '@vue/reactivity'
-import { EMPTY_OBJ, isFunction } from '@vue/shared'
+import { EMPTY_OBJ, isFunction, isString } from '@vue/shared'
 import {
   type RawProps,
   getPropsProxyHandlers,
   hasFallthroughAttrs,
   normalizePropsOptions,
+  resolveDynamicProps,
   setupPropsValidation,
 } from './componentProps'
-import { setDynamicProp } from './dom/prop'
 import { renderEffect } from './renderEffect'
 import { emit, normalizeEmitsOptions } from './componentEmits'
+import { setStyle } from './dom/style'
+import { setClass, setDynamicProp } from './dom/prop'
 
 export { currentInstance } from '@vue/runtime-dom'
 
@@ -266,7 +268,7 @@ export function isVaporComponent(
 export class SetupContext<E = EmitsOptions> {
   attrs: Record<string, any>
   emit: EmitFn<E>
-  // slots: Readonly<StaticSlots>
+  // TODO slots: Readonly<StaticSlots>
   expose: (exposed?: Record<string, any>) => void
 
   constructor(instance: VaporComponentInstance) {
@@ -278,3 +280,47 @@ export class SetupContext<E = EmitsOptions> {
     }
   }
 }
+
+export function createComponentWithFallback(
+  comp: VaporComponent | string,
+  rawProps: RawProps | undefined,
+  // TODO slots: RawSlots | null
+  isSingleRoot?: boolean,
+): HTMLElement | VaporComponentInstance {
+  if (!isString(comp)) {
+    return createComponent(comp, rawProps, isSingleRoot)
+  }
+
+  // eslint-disable-next-line no-restricted-globals
+  const el = document.createElement(comp)
+
+  if (rawProps) {
+    renderEffect(() => {
+      let classes: unknown[] | undefined
+      let styles: unknown[] | undefined
+      const resolved = resolveDynamicProps(rawProps)
+      for (const key in resolved) {
+        const value = resolved[key]
+        if (key === 'class') (classes ||= []).push(value)
+        else if (key === 'style') (styles ||= []).push(value)
+        else setDynamicProp(el, key, value)
+      }
+      if (classes) setClass(el, classes)
+      if (styles) setStyle(el, styles)
+    })
+  }
+
+  // TODO
+  // if (slots) {
+  //   if (!Array.isArray(slots)) slots = [slots]
+  //   for (let i = 0; i < slots.length; i++) {
+  //     const slot = slots[i]
+  //     if (!isDynamicSlotFn(slot) && slot.default) {
+  //       const block = slot.default && slot.default()
+  //       if (block) el.append(...normalizeBlock(block))
+  //     }
+  //   }
+  // }
+
+  return el
+}
index ff941d2ec5e45ada72e515e2c6e123ceb0acda95..e9336b5ed83749c25a8fdc9a52562c53f2a63d76 100644 (file)
@@ -231,29 +231,33 @@ export function setupPropsValidation(instance: VaporComponentInstance): void {
   const rawProps = instance.rawProps
   if (!rawProps) return
   renderEffect(() => {
-    const mergedRawProps: Record<string, any> = {}
-    for (const key in rawProps) {
-      if (key !== '$') {
-        mergedRawProps[key] = rawProps[key]()
-      }
-    }
-    if (rawProps.$) {
-      for (const source of rawProps.$) {
-        const isDynamic = isFunction(source)
-        const resolved = isDynamic ? source() : source
-        for (const key in resolved) {
-          mergedRawProps[key] = isDynamic
-            ? resolved[key]
-            : (resolved[key] as Function)()
-        }
-      }
-    }
     pushWarningContext(instance)
     validateProps(
-      mergedRawProps,
+      resolveDynamicProps(rawProps),
       instance.props,
       normalizePropsOptions(instance.type)[0]!,
     )
     popWarningContext()
   }, true /* noLifecycle */)
 }
+
+export function resolveDynamicProps(props: RawProps): Record<string, unknown> {
+  const mergedRawProps: Record<string, any> = {}
+  for (const key in props) {
+    if (key !== '$') {
+      mergedRawProps[key] = props[key]()
+    }
+  }
+  if (props.$) {
+    for (const source of props.$) {
+      const isDynamic = isFunction(source)
+      const resolved = isDynamic ? source() : source
+      for (const key in resolved) {
+        mergedRawProps[key] = isDynamic
+          ? resolved[key]
+          : (resolved[key] as Function)()
+      }
+    }
+  }
+  return mergedRawProps
+}
index a368fa6387829188bbb6f29f24b4db6e15bd9f4d..eeced2e2a0cfca124a401c873e34cf5bbb1dc349 100644 (file)
@@ -1,4 +1,4 @@
-export { createComponent } from './component'
+export { createComponent, createComponentWithFallback } from './component'
 export { renderEffect } from './renderEffect'
 export { createVaporApp } from './apiCreateApp'
 export { defineComponent } from './apiDefineComponent'
@@ -19,3 +19,6 @@ export {
 } from './dom/prop'
 export { on, delegate, delegateEvents, setDynamicEvents } from './dom/event'
 export { setRef } from './dom/templateRef'
+
+// re-exports
+export { resolveComponent } from '@vue/runtime-dom'