Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions packages/runtime-dom/src/components/TransitionGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ import {
} from '@vue/runtime-core'
import { extend } from '@vue/shared'

const positionMap = new WeakMap<VNode, DOMRect>()
const newPositionMap = new WeakMap<VNode, DOMRect>()
interface Position {
top: number
left: number
}

const positionMap = new WeakMap<VNode, Position>()
const newPositionMap = new WeakMap<VNode, Position>()
const moveCbKey = Symbol('_moveCb')
const enterCbKey = Symbol('_enterCb')

Expand Down Expand Up @@ -145,10 +150,10 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({
instance,
),
)
positionMap.set(
child,
(child.el as Element).getBoundingClientRect(),
)
positionMap.set(child, {
left: (child.el as HTMLElement).offsetLeft,
top: (child.el as HTMLElement).offsetTop,
})
}
}
}
Expand Down Expand Up @@ -189,7 +194,10 @@ function callPendingCbs(c: VNode) {
}

function recordPosition(c: VNode) {
newPositionMap.set(c, (c.el as Element).getBoundingClientRect())
newPositionMap.set(c, {
left: (c.el as HTMLElement).offsetLeft,
top: (c.el as HTMLElement).offsetTop,
})
}

function applyTranslation(c: VNode): VNode | undefined {
Expand Down
56 changes: 56 additions & 0 deletions packages/vue/__tests__/e2e/TransitionGroup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,62 @@ describe('e2e: TransitionGroup', () => {
E2E_TIMEOUT,
)

// #6105
test(
'with scale',
async () => {
await page().evaluate(() => {
const { createApp, ref, onMounted } = (window as any).Vue
createApp({
template: `
<div id="container">
<div class="scale" style="transform: scale(2) translateX(50%) translateY(50%)">
<transition-group tag="ul">
<li v-for="item in items" :key="item">{{item}}</li>
</transition-group>
<button id="toggleBtn" @click="click">button</button>
</div>
</div>
`,
setup: () => {
const items = ref(['a', 'b', 'c'])
const click = () => {
items.value.reverse()
}

onMounted(() => {
const styleNode = document.createElement('style')
styleNode.innerHTML = `.v-move {
transition: transform 0.5s ease;
}`
document.body.appendChild(styleNode)
})

return { items, click }
},
}).mount('#app')
})

const original_top = await page().$eval('ul li:nth-child(1)', node => {
return node.getBoundingClientRect().top
})
const new_top = await page().evaluate(() => {
const el = document.querySelector('ul li:nth-child(1)')
const p = new Promise(resolve => {
el!.addEventListener('transitionstart', () => {
const new_top = el!.getBoundingClientRect().top
resolve(new_top)
})
})
;(document.querySelector('#toggleBtn') as any)!.click()
return p
})

expect(original_top).toBeLessThan(new_top as number)
},
E2E_TIMEOUT,
)

test(
'not leaking after children unmounted',
async () => {
Expand Down
Loading