Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8142269

Browse files
committed
fix(runtime-vapor): animate vdom component moves in vapor TransitionGroup
1 parent cb584e8 commit 8142269

5 files changed

Lines changed: 131 additions & 4 deletions

File tree

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,5 +1134,43 @@ describe('vapor transition-group', () => {
11341134
`<div class=""><div>d</div></div>`,
11351135
)
11361136
})
1137+
1138+
test('keyed vdom component move after key change', async () => {
1139+
const btnSelector = '.keyed-vdom-component-move-after-key-change > button'
1140+
const containerSelector =
1141+
'.keyed-vdom-component-move-after-key-change > div'
1142+
1143+
await expect
1144+
.element(css(containerSelector))
1145+
.toContainHTML(
1146+
`<div class="item-wrapper">` +
1147+
`<div class="item closed" id="item-1"><div class="item-inner">item 1</div></div>` +
1148+
`<div class="item closed" id="item-2"><div class="item-inner">item 2</div></div>` +
1149+
`<!--for--></div><!--transition-group-->`,
1150+
)
1151+
1152+
click(btnSelector)
1153+
await nextTick()
1154+
await nextFrame()
1155+
1156+
await expect
1157+
.element(css(containerSelector))
1158+
.toContainHTML(
1159+
`<div class="item-wrapper">` +
1160+
`<div class="item opened" id="item-1"><div class="item-inner">item 1</div></div>` +
1161+
`<div class="item closed group-move" id="item-2" style=""><div class="item-inner">item 2</div></div>` +
1162+
`<!--for--></div><!--transition-group-->`,
1163+
)
1164+
1165+
await transitionFinish(350)
1166+
await expect
1167+
.element(css(containerSelector))
1168+
.toContainHTML(
1169+
`<div class="item-wrapper">` +
1170+
`<div class="item opened" id="item-1"><div class="item-inner">item 1</div></div>` +
1171+
`<div class="item closed" id="item-2" style=""><div class="item-inner">item 2</div></div>` +
1172+
`<!--for--></div><!--transition-group-->`,
1173+
)
1174+
})
11371175
})
11381176
})
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<script setup vapor>
2+
import { ref } from 'vue'
3+
import VdomExpandingItem from '../../components/VdomExpandingItem.vue'
4+
5+
const items = ref(
6+
[...Array(2)].map((_, i) => ({
7+
id: i + 1,
8+
isOpened: false,
9+
})),
10+
)
11+
12+
function toggleExpansion() {
13+
items.value[0].isOpened = !items.value[0].isOpened
14+
}
15+
</script>
16+
17+
<template>
18+
<div class="keyed-vdom-component-move-after-key-change">
19+
<button @click="toggleExpansion">toggle expansion of first element</button>
20+
<div>
21+
<transition-group name="group" tag="div" class="item-wrapper">
22+
<VdomExpandingItem
23+
v-for="i in items"
24+
:key="`${i.id}-${i.isOpened ? 'true' : 'false'}`"
25+
:id="i.id"
26+
:is-opened="i.isOpened"
27+
/>
28+
</transition-group>
29+
</div>
30+
</div>
31+
</template>
32+
33+
<style>
34+
.item-wrapper {
35+
display: flex;
36+
flex-wrap: wrap;
37+
gap: 5px;
38+
width: 430px;
39+
}
40+
41+
.keyed-vdom-component-move-after-key-change .group-move {
42+
transition: transform 300ms ease;
43+
}
44+
</style>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script setup lang="ts">
2+
defineProps<{
3+
id: number
4+
isOpened: boolean
5+
}>()
6+
</script>
7+
8+
<template>
9+
<div class="item" :class="isOpened ? 'opened' : 'closed'" :id="`item-${id}`">
10+
<div class="item-inner">item {{ id }}</div>
11+
</div>
12+
</template>
13+
14+
<style>
15+
.item {
16+
border: 1px solid black;
17+
width: 100px;
18+
height: 100px;
19+
display: flex;
20+
align-items: center;
21+
justify-content: center;
22+
}
23+
24+
.item.opened {
25+
width: 420px;
26+
}
27+
</style>

‎packages/runtime-vapor/src/components/TransitionGroup.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,12 @@ function getTransitionBlocks(
406406
children.push(...blocks)
407407
}
408408
} else if (isFragment(block)) {
409+
if (onFragment) onFragment(block)
410+
if (onUpdateOwner) onUpdateOwner(block)
409411
if (isInteropEnabled && block.vnode) {
410412
// vdom component
411413
children.push(block)
412414
} else {
413-
if (onFragment) onFragment(block)
414-
if (onUpdateOwner) onUpdateOwner(block)
415415
const blocks = getTransitionBlocks(block.nodes, onFragment, onUpdateOwner)
416416
inheritKey(blocks, block.$key)
417417
children.push(...blocks)

‎packages/runtime-vapor/src/vdomInterop.ts‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -820,13 +820,31 @@ function appendVnodeUpdatedHook(vnode: VNode, hook: () => void): void {
820820
: hook
821821
}
822822

823+
function appendVnodeBeforeUpdateHook(vnode: VNode, hook: () => void): void {
824+
const props = (vnode.props ||= {})
825+
const existing = props.onVnodeBeforeUpdate
826+
props.onVnodeBeforeUpdate = existing
827+
? isArray(existing)
828+
? [...existing, hook]
829+
: [existing, hook]
830+
: hook
831+
}
832+
823833
function trackFragmentVNodeUpdates(frag: VaporFragment, vnode: VNode): void {
824-
const refresh = () => {
834+
const beforeUpdate = () => {
835+
if (frag.onBeforeUpdate) {
836+
for (let i = 0; i < frag.onBeforeUpdate.length; i++) {
837+
frag.onBeforeUpdate[i]()
838+
}
839+
}
840+
}
841+
const updated = () => {
825842
frag.nodes = resolveVNodeNodes(vnode)
826843
frag.validityPending = false
827844
if (frag.onUpdated) frag.onUpdated.forEach(m => m())
828845
}
829-
appendVnodeUpdatedHook(vnode, refresh)
846+
appendVnodeBeforeUpdateHook(vnode, beforeUpdate)
847+
appendVnodeUpdatedHook(vnode, updated)
830848
}
831849

832850
/**

0 commit comments

Comments
 (0)