]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(teleport/css-v-bind): fix css v-bind in teleport in child component slot
authorEvan You <yyx990803@gmail.com>
Thu, 10 Nov 2022 07:08:25 +0000 (15:08 +0800)
committerEvan You <yyx990803@gmail.com>
Thu, 10 Nov 2022 07:08:25 +0000 (15:08 +0800)
packages/runtime-core/src/components/Teleport.ts
packages/runtime-core/src/vnode.ts
packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts

index 18c4aee86a056b780a40e943b87e9fa38a5ec2c6..f9f845298dca079c88d2806b145c56cd8e64b45c 100644 (file)
@@ -223,7 +223,7 @@ export const TeleportImpl = {
       }
     }
 
-    updateCssVars(parentComponent, n2)
+    updateCssVars(n2)
   },
 
   remove(
@@ -385,7 +385,7 @@ function hydrateTeleport(
         )
       }
     }
-    updateCssVars(parentComponent, vnode)
+    updateCssVars(vnode)
   }
   return vnode.anchor && nextSibling(vnode.anchor as Node)
 }
@@ -396,19 +396,16 @@ export const Teleport = TeleportImpl as unknown as {
   new (): { $props: VNodeProps & TeleportProps }
 }
 
-function updateCssVars(
-  parentComponent: ComponentInternalInstance | null,
-  vnode: VNode
-) {
+function updateCssVars(vnode: VNode) {
   // presence of .ut method indicates owner component uses css vars.
   // code path here can assume browser environment.
-  if (parentComponent && parentComponent.ut) {
+  const ctx = vnode.ctx
+  if (ctx && ctx.ut) {
     let node = (vnode.children as VNode[])[0].el!
     while (node !== vnode.targetAnchor) {
-      if (node.nodeType === 1)
-        node.setAttribute('data-v-owner', parentComponent.uid)
+      if (node.nodeType === 1) node.setAttribute('data-v-owner', ctx.uid)
       node = node.nextSibling
     }
-    parentComponent.ut()
+    ctx.ut()
   }
 }
index 2122f9f855aa6009e8945f2ed2ad3705a0411138..7d8017e650a3b1d2f04030eb7e097b35311de4db 100644 (file)
@@ -205,6 +205,11 @@ export interface VNode<
   // application root node only
   appContext: AppContext | null
 
+  /**
+   * @internal lexical scope owner instance
+   */
+  ctx: ComponentInternalInstance | null
+
   /**
    * @internal attached by v-memo
    */
@@ -439,7 +444,8 @@ function createBaseVNode(
     patchFlag,
     dynamicProps,
     dynamicChildren: null,
-    appContext: null
+    appContext: null,
+    ctx: currentRenderingInstance
   } as VNode
 
   if (needFullChildrenNormalization) {
@@ -661,7 +667,8 @@ export function cloneVNode<T, U>(
     ssContent: vnode.ssContent && cloneVNode(vnode.ssContent),
     ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback),
     el: vnode.el,
-    anchor: vnode.anchor
+    anchor: vnode.anchor,
+    ctx: vnode.ctx
   }
   if (__COMPAT__) {
     defineLegacyVNodeProperties(cloned as VNode)
index e9dd36596506866d7a2492250df816e8714443f8..7d24ec0f43464443dc1ae0f902c026bbdd8436bd 100644 (file)
@@ -218,6 +218,30 @@ describe('useCssVars', () => {
     }
   })
 
+  test('with teleport in child slot', async () => {
+    document.body.innerHTML = ''
+    const state = reactive({ color: 'red' })
+    const root = document.createElement('div')
+    const target = document.body
+
+    const Child: FunctionalComponent = (_, { slots }) => {
+      return h('div', slots.default && slots.default())
+    }
+
+    const App = {
+      setup() {
+        useCssVars(() => state)
+        return () => h(Child, () => [h(Teleport, { to: target }, [h('div')])])
+      }
+    }
+
+    render(h(App), root)
+    await nextTick()
+    for (const c of [].slice.call(target.children as any)) {
+      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
+    }
+  })
+
   test('with teleport(change subTree)', async () => {
     document.body.innerHTML = ''
     const state = reactive({ color: 'red' })