daiwei vor 1 Jahr
Ursprung
Commit
4aaa69ae49

+ 5 - 1
packages/runtime-core/src/index.ts

@@ -505,7 +505,11 @@ export { type VaporInteropInterface } from './apiCreateApp'
 /**
  * @internal
  */
-export { type RendererInternals, MoveType } from './renderer'
+export {
+  type RendererInternals,
+  MoveType,
+  getInheritedScopeIds,
+} from './renderer'
 /**
  * @internal
  */

+ 54 - 24
packages/runtime-core/src/renderer.ts

@@ -764,30 +764,9 @@ function baseCreateRenderer(
         hostSetScopeId(el, slotScopeIds[i])
       }
     }
-    let subTree = parentComponent && parentComponent.subTree
-    if (subTree) {
-      if (
-        __DEV__ &&
-        subTree.patchFlag > 0 &&
-        subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
-      ) {
-        subTree =
-          filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
-      }
-      if (
-        vnode === subTree ||
-        (isSuspense(subTree.type) &&
-          (subTree.ssContent === vnode || subTree.ssFallback === vnode))
-      ) {
-        const parentVNode = parentComponent!.vnode!
-        setScopeId(
-          el,
-          parentVNode,
-          parentVNode.scopeId,
-          parentVNode.slotScopeIds,
-          parentComponent!.parent,
-        )
-      }
+    const inheritedScopeIds = getInheritedScopeIds(vnode, parentComponent)
+    for (let i = 0; i < inheritedScopeIds.length; i++) {
+      hostSetScopeId(el, inheritedScopeIds[i])
     }
   }
 
@@ -2656,3 +2635,54 @@ function getVaporInterface(
   }
   return res!
 }
+
+/**
+ * shared between vdom and vapor
+ */
+export function getInheritedScopeIds(
+  vnode: VNode,
+  parentComponent: GenericComponentInstance | null,
+): string[] {
+  const inheritedScopeIds: string[] = []
+
+  let currentParent = parentComponent
+  let currentVNode = vnode
+
+  while (currentParent) {
+    let subTree = currentParent.subTree
+    if (!subTree) break
+
+    if (
+      __DEV__ &&
+      subTree.patchFlag > 0 &&
+      subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
+    ) {
+      subTree =
+        filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
+    }
+
+    if (
+      currentVNode === subTree ||
+      (isSuspense(subTree.type) &&
+        (subTree.ssContent === currentVNode ||
+          subTree.ssFallback === currentVNode))
+    ) {
+      const parentVNode = currentParent.vnode!
+
+      if (parentVNode.scopeId) {
+        inheritedScopeIds.push(parentVNode.scopeId)
+      }
+
+      if (parentVNode.slotScopeIds) {
+        inheritedScopeIds.push(...parentVNode.slotScopeIds)
+      }
+
+      currentVNode = parentVNode
+      currentParent = currentParent.parent
+    } else {
+      break
+    }
+  }
+
+  return inheritedScopeIds
+}

+ 45 - 1
packages/runtime-vapor/__tests__/scopeId.spec.ts

@@ -321,6 +321,50 @@ describe('vdom interop', () => {
     )
   })
 
+  test('vdom parent > vapor > vapor > vdom child', () => {
+    const InnerVdomChild = {
+      __scopeId: 'inner-vdom-child',
+      setup() {
+        return () => h('button')
+      },
+    }
+
+    const VaporChild = defineVaporComponent({
+      __scopeId: 'vapor-child',
+      setup() {
+        return createComponent(InnerVdomChild as any, null, null, true)
+      },
+    })
+
+    const VaporChild2 = defineVaporComponent({
+      __scopeId: 'vapor-child2',
+      setup() {
+        return createComponent(VaporChild as any, null, null, true)
+      },
+    })
+
+    const VdomChild = {
+      __scopeId: 'vdom-child',
+      setup() {
+        return () => h(VaporChild2 as any)
+      },
+    }
+
+    const App = {
+      __scopeId: 'parent',
+      setup() {
+        return () => h(VdomChild)
+      },
+    }
+
+    const root = document.createElement('div')
+    createApp(App).use(vaporInteropPlugin).mount(root)
+
+    expect(root.innerHTML).toBe(
+      `<button inner-vdom-child="" vapor-child="" vapor-child2="" vdom-child="" parent=""></button>`,
+    )
+  })
+
   test('vdom parent > vapor dynamic child', () => {
     const VaporChild = defineVaporComponent({
       __scopeId: 'vapor-child',
@@ -418,7 +462,7 @@ describe('vdom interop', () => {
     )
   })
 
-  test.todo('vapor parent > vdom > vdom > vapor child', () => {
+  test('vapor parent > vdom > vdom > vapor child', () => {
     const InnerVaporChild = defineVaporComponent({
       __scopeId: 'inner-vapor-child',
       setup() {

+ 6 - 1
packages/runtime-vapor/src/block.ts

@@ -8,6 +8,7 @@ import {
 import { createComment, createTextNode } from './dom/node'
 import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
 import { isHydrating } from './dom/hydration'
+import { getInheritedScopeIds } from '@vue/runtime-dom'
 
 export type Block =
   | Node
@@ -213,12 +214,16 @@ export function setComponentScopeId(instance: VaporComponentInstance): void {
     setScopeId(instance.block, scopeId)
   }
 
-  // vdom parent
+  // inherit scopeId from vdom parent
   if (
     parent.subTree &&
     (parent.subTree.component as any) === instance &&
     parent.vnode!.scopeId
   ) {
     setScopeId(instance.block, parent.vnode!.scopeId)
+    const scopeIds = getInheritedScopeIds(parent.vnode!, parent.parent)
+    for (const id of scopeIds) {
+      setScopeId(instance.block, id)
+    }
   }
 }