Skip to content

Commit cc0d96f

Browse files
committed
fix(transition): isolate transition leaving cache by resolved child type
1 parent 5348391 commit cc0d96f

File tree

5 files changed

+304
-34
lines changed

5 files changed

+304
-34
lines changed

packages-private/vapor-e2e-test/__tests__/transition.spec.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,56 @@ describe('vapor transition', () => {
13161316
'<div class="">vapor compA</div>',
13171317
)
13181318
})
1319+
1320+
test(
1321+
'different pre-resolved async types during leave',
1322+
async () => {
1323+
const rootSelector = '.different-pre-resolved-async-types-during-leave'
1324+
const btnSelector = `${rootSelector} > button`
1325+
const hiddenASelector = `${rootSelector} #hidden-a`
1326+
const hiddenBSelector = `${rootSelector} #hidden-b`
1327+
const containerSelector = `${rootSelector} #container`
1328+
1329+
await waitForInnerHTML(
1330+
hiddenASelector,
1331+
'<div style="display: none;">vapor compA</div>',
1332+
)
1333+
await waitForInnerHTML(
1334+
hiddenBSelector,
1335+
'<div style="display: none;">vapor compB</div>',
1336+
)
1337+
await waitForInnerHTML(containerSelector, '<div>vapor compA</div>')
1338+
1339+
await page().evaluate(() => {
1340+
;(window as any).resetCalls()
1341+
})
1342+
await domClick(btnSelector)
1343+
await nextTick()
1344+
1345+
let calls = await page().evaluate(() => {
1346+
return (window as any).getCalls()
1347+
})
1348+
expect(calls).toContain('beforeEnter:vapor compB')
1349+
expect(calls).toContain('enter:vapor compB')
1350+
expect(calls).toContain('beforeLeave:vapor compA')
1351+
expect(calls).toContain('leave:vapor compA')
1352+
expect(calls).not.toContain('afterLeave:vapor compA')
1353+
1354+
await timeout(50 + buffer)
1355+
calls = await page().evaluate(() => {
1356+
return (window as any).getCalls()
1357+
})
1358+
expect(calls).toStrictEqual([
1359+
'beforeLeave:vapor compA',
1360+
'leave:vapor compA',
1361+
'beforeEnter:vapor compB',
1362+
'enter:vapor compB',
1363+
'afterLeave:vapor compA',
1364+
'afterEnter:vapor compB',
1365+
])
1366+
},
1367+
E2E_TIMEOUT,
1368+
)
13191369
})
13201370

13211371
describe('transition with v-show', () => {
@@ -1788,6 +1838,44 @@ describe('vapor transition', () => {
17881838
)
17891839
})
17901840

1841+
describe('dynamic component', () => {
1842+
test(
1843+
'different type during leave',
1844+
async () => {
1845+
const btnSelector = '.different-type-during-leave > button'
1846+
1847+
await page().evaluate(() => {
1848+
;(window as any).resetCalls()
1849+
})
1850+
await domClick(btnSelector)
1851+
await nextTick()
1852+
1853+
let calls = await page().evaluate(() => {
1854+
return (window as any).getCalls()
1855+
})
1856+
expect(calls).toContain('beforeEnter:span')
1857+
expect(calls).toContain('enter:span')
1858+
expect(calls).toContain('beforeLeave:div')
1859+
expect(calls).toContain('leave:div')
1860+
expect(calls).not.toContain('afterLeave:div')
1861+
1862+
await timeout(50 + buffer)
1863+
calls = await page().evaluate(() => {
1864+
return (window as any).getCalls()
1865+
})
1866+
expect(calls).toStrictEqual([
1867+
'beforeLeave:div',
1868+
'leave:div',
1869+
'beforeEnter:span',
1870+
'enter:span',
1871+
'afterLeave:div',
1872+
'afterEnter:span',
1873+
])
1874+
},
1875+
E2E_TIMEOUT,
1876+
)
1877+
})
1878+
17911879
describe('mode', () => {
17921880
test(
17931881
'in-out mode with v-if',
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script setup vapor lang="ts">
2+
import { computed, ref } from 'vue'
3+
4+
const tags = ['div', 'span', 'p']
5+
const view = ref(0)
6+
const calls: string[] = []
7+
const wait = (fn: () => void, time: number) => setTimeout(fn, time)
8+
9+
const advanceView = () => {
10+
view.value = (view.value + 1) % tags.length
11+
}
12+
13+
const currentTag = computed(() => tags[view.value])
14+
15+
;(window as any).getCalls = () => [...calls]
16+
;(window as any).resetCalls = () => {
17+
calls.length = 0
18+
}
19+
20+
const record = (phase: string, el: Element) => {
21+
calls.push(`${phase}:${el.tagName.toLowerCase()}`)
22+
}
23+
</script>
24+
25+
<template>
26+
<div class="different-type-during-leave">
27+
<button @click="advanceView">toggle</button>
28+
<div>
29+
<transition
30+
:css="false"
31+
@before-enter="el => record('beforeEnter', el)"
32+
@enter="
33+
(el, done) => {
34+
record('enter', el)
35+
wait(done, 50)
36+
}
37+
"
38+
@after-enter="el => record('afterEnter', el)"
39+
@before-leave="el => record('beforeLeave', el)"
40+
@leave="
41+
(el, done) => {
42+
record('leave', el)
43+
wait(done, 50)
44+
}
45+
"
46+
@after-leave="el => record('afterLeave', el)"
47+
>
48+
<component :is="currentTag">content</component>
49+
</transition>
50+
</div>
51+
</div>
52+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<script setup vapor lang="ts">
2+
import { computed, defineVaporAsyncComponent, ref } from 'vue'
3+
import VaporCompA from '../../components/VaporCompA.vue'
4+
import VaporCompB from '../../components/VaporCompB.vue'
5+
6+
const AsyncCompResolvedA = defineVaporAsyncComponent(() =>
7+
Promise.resolve(VaporCompA),
8+
)
9+
const AsyncCompResolvedB = defineVaporAsyncComponent(() =>
10+
Promise.resolve(VaporCompB),
11+
)
12+
13+
const components = [AsyncCompResolvedA, AsyncCompResolvedB]
14+
const view = ref(0)
15+
const calls: string[] = []
16+
const wait = (fn: () => void, time: number) => setTimeout(fn, time)
17+
18+
const advanceView = () => {
19+
view.value = (view.value + 1) % components.length
20+
}
21+
22+
const currentComponent = computed(() => components[view.value])
23+
24+
;(window as any).getCalls = () => [...calls]
25+
;(window as any).resetCalls = () => {
26+
calls.length = 0
27+
}
28+
29+
const record = (phase: string, el: Element) => {
30+
calls.push(`${phase}:${el.textContent?.trim()}`)
31+
}
32+
</script>
33+
34+
<template>
35+
<div class="different-pre-resolved-async-types-during-leave">
36+
<div id="hidden-a">
37+
<AsyncCompResolvedA v-show="false" />
38+
</div>
39+
<div id="hidden-b">
40+
<AsyncCompResolvedB v-show="false" />
41+
</div>
42+
<button @click="advanceView">toggle</button>
43+
<div id="container">
44+
<transition
45+
:css="false"
46+
@before-enter="el => record('beforeEnter', el)"
47+
@enter="
48+
(el, done) => {
49+
record('enter', el)
50+
wait(done, 50)
51+
}
52+
"
53+
@after-enter="el => record('afterEnter', el)"
54+
@before-leave="el => record('beforeLeave', el)"
55+
@leave="
56+
(el, done) => {
57+
record('leave', el)
58+
wait(done, 50)
59+
}
60+
"
61+
@after-leave="el => record('afterLeave', el)"
62+
>
63+
<component :is="currentComponent" />
64+
</transition>
65+
</div>
66+
</div>
67+
</template>

0 commit comments

Comments
 (0)