diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index 0a6e302a1f5..0391900dbd2 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -67,6 +67,7 @@ export interface TransitionHooks< delayedLeave: () => void ): void delayedLeave?(): void + effects: Function[] } export type TransitionHookCaller = ( @@ -83,6 +84,7 @@ export interface TransitionState { // Track pending leave callbacks for children of the same key. // This is used to force remove leaving a child when a new copy is entering. leavingVNodes: Map> + effects: Function[] } export interface TransitionElement { @@ -98,7 +100,8 @@ export function useTransitionState(): TransitionState { isMounted: false, isLeaving: false, isUnmounting: false, - leavingVNodes: new Map() + leavingVNodes: new Map(), + effects: [] } onMounted(() => { state.isMounted = true @@ -317,6 +320,7 @@ export function resolveTransitionHooks( const hooks: TransitionHooks = { mode, persisted, + effects: state.effects, beforeEnter(el) { let hook = onBeforeEnter if (!state.isMounted) { @@ -340,6 +344,12 @@ export function resolveTransitionHooks( // force early removal (not cancelled) leavingVNode.el!._leaveCb() } + + state.effects.forEach(fn => { + fn(el) + }) + state.effects = [] + callHook(hook, [el]) }, diff --git a/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts b/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts index a72d0a9c2df..a44c32da88a 100644 --- a/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts +++ b/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts @@ -7,7 +7,8 @@ import { reactive, nextTick, ComponentOptions, - Suspense + Suspense, + Transition } from '@vue/runtime-dom' describe('useCssVars', () => { @@ -163,4 +164,32 @@ describe('useCssVars', () => { expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red') } }) + + test('with transition + v-if', async () => { + const state = reactive({ color: 'red' }) + const value = ref(true) + const root = document.createElement('div') + + const App = { + setup() { + useCssVars(() => state) + return () => + h(Transition, null, { + default: () => (value.value ? [h('div')] : [h('span')]) + }) + } + } + + render(h(App), root) + await nextTick() + for (const c of [].slice.call(root.children as any)) { + expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`) + } + + value.value = false + await nextTick() + for (const c of [].slice.call(root.children as any)) { + expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red') + } + }) }) diff --git a/packages/runtime-dom/src/helpers/useCssVars.ts b/packages/runtime-dom/src/helpers/useCssVars.ts index 3253dd22731..6fa5d26f72f 100644 --- a/packages/runtime-dom/src/helpers/useCssVars.ts +++ b/packages/runtime-dom/src/helpers/useCssVars.ts @@ -47,6 +47,12 @@ function setVarsOnVNode(vnode: VNode, vars: Record) { vnode = vnode.component.subTree } + if (vnode.transition) { + vnode.transition.effects.push((el: Node) => { + setVarsOnNode(el, vars) + }) + } + if (vnode.shapeFlag & ShapeFlags.ELEMENT && vnode.el) { setVarsOnNode(vnode.el as Node, vars) } else if (vnode.type === Fragment) {