]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(custom-element): update slot nodes when shadowRoot is false
authordaiwei <daiwei521@126.com>
Wed, 16 Apr 2025 03:34:33 +0000 (11:34 +0800)
committerdaiwei <daiwei521@126.com>
Wed, 16 Apr 2025 03:34:33 +0000 (11:34 +0800)
packages/runtime-core/src/helpers/renderSlot.ts
packages/runtime-core/src/renderer.ts
packages/runtime-core/src/vnode.ts
packages/runtime-dom/src/apiCustomElement.ts

index 92f7dab36b621f2be3cf2b7a49ea2e9b066f6123..aec49d1eaea738890866cba7090a1d2751238953 100644 (file)
@@ -96,6 +96,7 @@ export function renderSlot(
   if (slot && (slot as ContextualRenderFn)._c) {
     ;(slot as ContextualRenderFn)._d = true
   }
+  rendered.slotName = name
   return rendered
 }
 
index 05c4ac345eb81f9e030bc2078febc24c22f1dfe6..9494dac09d8e6cfbd0fffad55413927de0e1577c 100644 (file)
@@ -934,6 +934,10 @@ function baseCreateRenderer(
         dirs && invokeDirectiveHook(n2, n1, parentComponent, 'updated')
       }, parentSuspense)
     }
+
+    if (el._isVueCE && !el._def.shadowRoot) {
+      el._updateSlots(n2.children)
+    }
   }
 
   // The fast path for blocks.
index a8c5340cd1fe167840f700e34a2a25b1909eb048..a146cdc162a38b45894ba6a9b8fdf2ba020fd981 100644 (file)
@@ -253,6 +253,10 @@ export interface VNode<
    * @internal custom element interception hook
    */
   ce?: (instance: ComponentInternalInstance) => void
+  /**
+   * @internal
+   */
+  slotName?: string
 }
 
 // Since v-if and v-for are the two possible ways node structure can dynamically
@@ -715,6 +719,7 @@ export function cloneVNode<T, U>(
     anchor: vnode.anchor,
     ctx: vnode.ctx,
     ce: vnode.ce,
+    slotName: vnode.slotName,
   }
 
   // if the vnode will be replaced by the cloned one, it is necessary
index aeeaeec9b9f8445869107370666010ede7761526..5cab16ad6790fe45fc16a8d2e9fdcfb3c86b1e5a 100644 (file)
@@ -19,15 +19,18 @@ import {
   type EmitsOptions,
   type EmitsToProps,
   type ExtractPropTypes,
+  Fragment,
   type MethodOptions,
   type RenderFunction,
   type SetupContext,
   type SlotsType,
   type VNode,
+  type VNodeArrayChildren,
   type VNodeProps,
   createVNode,
   defineComponent,
   getCurrentInstance,
+  isVNode,
   nextTick,
   unref,
   warn,
@@ -657,6 +660,17 @@ export class VueElement
     }
   }
 
+  /**
+   * @internal
+   */
+  _updateSlots(children: VNode[]): void {
+    children.forEach(child => {
+      this._slots![child.slotName!] = collectElements(
+        child.children as VNodeArrayChildren,
+      )
+    })
+  }
+
   /**
    * @internal
    */
@@ -710,3 +724,19 @@ export function useShadowRoot(): ShadowRoot | null {
   const el = __DEV__ ? useHost('useShadowRoot') : useHost()
   return el && el.shadowRoot
 }
+
+function collectElements(children: VNodeArrayChildren): Node[] {
+  const nodes: Node[] = []
+  for (const vnode of children) {
+    if (isArray(vnode)) {
+      nodes.push(...collectElements(vnode))
+    } else if (isVNode(vnode)) {
+      if (vnode.type === Fragment) {
+        nodes.push(...collectElements(vnode.children as VNodeArrayChildren))
+      } else if (vnode.el) {
+        nodes.push(vnode.el as Node)
+      }
+    }
+  }
+  return nodes
+}