From 767d212d20a9a488d183610d048ba131bbfd067e Mon Sep 17 00:00:00 2001 From: edison Date: Thu, 14 Apr 2022 17:10:41 +0800 Subject: [PATCH] fix(transition): fix broken leave transition on dev root fragment (#5268) --- packages/runtime-core/src/renderer.ts | 18 +++++- packages/vue/__tests__/Transition.spec.ts | 74 ++++++++++++++++++++++- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 0a215a14b76..ed698d21f7b 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -2159,7 +2159,23 @@ function baseCreateRenderer( const remove: RemoveFn = vnode => { const { type, el, anchor, transition } = vnode if (type === Fragment) { - removeFragment(el!, anchor!) + if ( + __DEV__ && + vnode.patchFlag > 0 && + vnode.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT && + transition && + !transition.persisted + ) { + ;(vnode.children as VNode[]).forEach(child => { + if (child.type === Comment) { + hostRemove(child.el!) + } else { + remove(child) + } + }) + } else { + removeFragment(el!, anchor!) + } return } diff --git a/packages/vue/__tests__/Transition.spec.ts b/packages/vue/__tests__/Transition.spec.ts index 97b3ccd9625..37204939511 100644 --- a/packages/vue/__tests__/Transition.spec.ts +++ b/packages/vue/__tests__/Transition.spec.ts @@ -1979,9 +1979,7 @@ describe('e2e: Transition', () => { ` }).mount(document.createElement('div')) - expect( - `invalid mode: none` - ).toHaveBeenWarned() + expect(`invalid mode: none`).toHaveBeenWarned() }) // #3227 @@ -2023,4 +2021,74 @@ describe('e2e: Transition', () => { expect(outerSpy).toHaveBeenCalledTimes(1) expect(root.innerHTML).toBe(``) }) + + test( + 'should work with dev root fragment', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + components: { + Comp: { + template: ` + +
+ ` + } + }, + template: ` +
+ + +
content
+
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + expect(await html('#container')).toBe( + '
content
' + ) + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'v-leave-from', + 'v-leave-active' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'v-leave-active', + 'v-leave-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('') + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'v-enter-from', + 'v-enter-active' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'v-enter-active', + 'v-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe( + '
content
' + ) + }, + E2E_TIMEOUT + ) })