Skip to content

Commit 73ac2e7

Browse files
committed
fix(core): transition animation of leaving not take effect(close #52)
1 parent 35bae2f commit 73ac2e7

File tree

4 files changed

+89
-1
lines changed

4 files changed

+89
-1
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@
44
.idea
55
packages/docs/.vitepress/cache
66
coverage
7+
8+
.cunzhi-memory

packages/core/src/styled.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ import { generateClassName, generateComponentName, injectStyle, insertExpression
1212
import {
1313
computed,
1414
defineComponent,
15+
getCurrentInstance,
1516
h,
1617
inject,
18+
nextTick,
1719
onMounted,
1820
onUnmounted,
1921
reactive,
@@ -100,6 +102,53 @@ type TransformProps<T> = {
100102
: ConstructorToType<T[K]>
101103
}
102104

105+
// {{ AURA-X: Add - 实现 transition 友好的样式移除函数. Approval: 寸止. }}
106+
function removeStyleWithTransition(className: string): void {
107+
const instance = getCurrentInstance()
108+
if (!instance) {
109+
// 如果无法获取组件实例,直接移除样式
110+
removeStyle(className)
111+
return
112+
}
113+
114+
nextTick(() => {
115+
const el = instance.vnode.el as HTMLElement
116+
if (!el) {
117+
removeStyle(className)
118+
return
119+
}
120+
121+
// 检查元素是否有 transition 样式
122+
const computedStyle = window.getComputedStyle(el)
123+
const transitionDuration = computedStyle.transitionDuration
124+
const transitionProperty = computedStyle.transitionProperty
125+
126+
// 如果没有 transition 或 transition 时间为 0,直接移除样式
127+
if (!transitionDuration || transitionDuration === '0s' || transitionProperty === 'none') {
128+
removeStyle(className)
129+
return
130+
}
131+
132+
// 监听 transitionend 事件
133+
const handleTransitionEnd = (event: TransitionEvent) => {
134+
// 确保事件来自当前元素
135+
if (event.target === el) {
136+
el.removeEventListener('transitionend', handleTransitionEnd)
137+
removeStyle(className)
138+
}
139+
}
140+
141+
el.addEventListener('transitionend', handleTransitionEnd)
142+
143+
// 设置超时保护,防止 transitionend 事件未触发
144+
const maxDuration = Number.parseFloat(transitionDuration) * 1000 + 100 // 添加 100ms 缓冲
145+
setTimeout(() => {
146+
el.removeEventListener('transitionend', handleTransitionEnd)
147+
removeStyle(className)
148+
}, maxDuration)
149+
})
150+
}
151+
103152
function baseStyled<T extends object>(target: string | InstanceType<any>, propsDefinition?: PropsDefinition<T>, defaultAttrs?: unknown): StyledComponent<T> {
104153
if (!isValidElementType(target)) {
105154
throw new Error('The element is invalid.')
@@ -249,7 +298,8 @@ function baseStyled<T extends object>(target: string | InstanceType<any>, propsD
249298
})
250299

251300
onUnmounted(() => {
252-
removeStyle(defaultClassName)
301+
// {{ AURA-X: Modify - 实现 transition 友好的样式移除机制. Approval: 寸止. }}
302+
removeStyleWithTransition(defaultClassName)
253303
})
254304

255305
// Return the render function

packages/playground/src/App.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import StressTests from './components/StressTests.vue'
77
import ThemeTests from './components/ThemeTests.vue'
88
import PropsTest from './components/PropsTest.vue'
99
import DebugPanel from './components/DebugPanel.vue'
10+
import TransitionTest from './TransitionTest.vue'
1011
1112
// 主题配置
1213
const theme = reactive({
@@ -176,6 +177,8 @@ const exportReport = () => {
176177

177178
<template>
178179
<ThemeProvider :theme="theme">
180+
<TransitionTest />
181+
179182
<AppContainer>
180183
<Header>
181184
<h1>Vue Styled Components Playground</h1>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<template>
2+
<button @click="toggle">Toggle</button>
3+
<transition name="trans">
4+
<StyledBox v-if="visible" />
5+
</transition>
6+
</template>
7+
8+
<script setup>
9+
import { styled } from "@vue-styled-components/core";
10+
import { ref } from "vue";
11+
12+
const StyledBox = styled.div`
13+
width: 100px;
14+
height: 100px;
15+
background: red;
16+
`;
17+
18+
const visible = ref(true);
19+
function toggle() {
20+
visible.value = !visible.value;
21+
}
22+
</script>
23+
24+
<style>
25+
.trans-enter-active,
26+
.trans-leave-active {
27+
transition: transform 0.5s ease;
28+
}
29+
.trans-enter-from,
30+
.trans-leave-to {
31+
transform: translateY(100%);
32+
}
33+
</style>

0 commit comments

Comments
 (0)