diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 3481fc3385c..1e8ff8941a1 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -519,7 +519,14 @@ export interface ComponentInternalInstance { * @internal */ ut?: (vars?: Record) => void - + /** + * `update nested teleport css vars` + * @internal + */ + parentUt?: { + uid: number + ut: (vars?: Record) => void + } /** * dev only. For style v-bind hydration mismatch checks * @internal diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts index 8d174e2022c..30baea40703 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/packages/runtime-core/src/components/Teleport.ts @@ -432,4 +432,13 @@ function updateCssVars(vnode: VNode) { } ctx.ut() } + if (ctx && ctx.parentUt) { + let node = (vnode.children as VNode[])[0].el! + while (node && node !== vnode.targetAnchor) { + if (node.nodeType === 1) + node.setAttribute(`data-v-parent-${ctx.parentUt.uid}-owner`, '') + node = node.nextSibling + } + ctx.parentUt.ut() + } } diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 0e2a4bafcc5..73707388a63 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -463,7 +463,16 @@ function createBaseVNode( appContext: null, ctx: currentRenderingInstance, } as VNode - + // eslint-disable-next-line no-restricted-syntax + if (vnode.ctx && currentRenderingInstance?.parent?.ut) { + vnode.ctx.parentUt = { + ut: currentRenderingInstance.parent.ut, + uid: currentRenderingInstance.parent.uid, + } + } + if (vnode.ctx && vnode.ctx.parent && vnode.ctx.parent.parentUt) { + vnode.ctx.parentUt = vnode.ctx.parent.parentUt + } if (needFullChildrenNormalization) { normalizeChildren(vnode, children) // normalize suspense children diff --git a/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts b/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts index 9f860a5e3c3..587fa61c689 100644 --- a/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts +++ b/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts @@ -274,7 +274,38 @@ describe('useCssVars', () => { expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red') } }) + test('with nested teleport', async () => { + document.body.innerHTML = '' + const state = { color: 'red' } + const root = document.createElement('div') + const target = document.body + const App = { + setup() { + useCssVars(() => state) + return () => h(Comp) + }, + } + const Comp = { + setup() { + return () => h(NestedTeleport) + }, + } + const NestedTeleport = { + setup() { + return () => + h( + Teleport, + { to: target }, + h('div', { class: 'color' }, 'Another teleport'), + ) + }, + } + render(h(App), root) + await nextTick() + const dom: HTMLElement = target.querySelector('.color')! + expect(dom.style.getPropertyValue(`--color`)).toBe('red') + }) test('with teleport in child slot', async () => { document.body.innerHTML = '' const state = reactive({ color: 'red' }) diff --git a/packages/runtime-dom/src/helpers/useCssVars.ts b/packages/runtime-dom/src/helpers/useCssVars.ts index 286a4176076..7b07fe6422c 100644 --- a/packages/runtime-dom/src/helpers/useCssVars.ts +++ b/packages/runtime-dom/src/helpers/useCssVars.ts @@ -30,6 +30,9 @@ export function useCssVars(getter: (ctx: any) => Record) { Array.from( document.querySelectorAll(`[data-v-owner="${instance.uid}"]`), ).forEach(node => setVarsOnNode(node, vars)) + Array.from( + document.querySelectorAll(`[data-v-parent-${instance.uid}-owner]`), + ).forEach(node => setVarsOnNode(node, vars)) }) if (__DEV__) {