Transition 过渡动画
17:06说明
进出场过渡封装:以 CSS transition + 类切换驱动内容显隐(uni-app x App 端不支持 @keyframes,故不依赖它),内置 fade / slide-* / zoom-* 七种预设,duration / timing-function / delay 可调。动画完成按 duration + delay 的定时器判定(App 端 transitionend 可能不触发),因此 after-enter / after-leave 在设定时长后触发。
兼容性
| 平台 | 支持情况 |
|---|---|
| App | ✅ 支持(动画走 CSS transition + 类切换,不使用 @keyframes;完成判定用时长定时器,不依赖 transitionend) |
| H5 | ✅ 支持 |
| 微信小程序 | ✅ 支持 |
示例
基础用法
show 控制内容显隐,默认 fade 淡入淡出;组件只负责过渡,内容高度由用户自定。
查看源码
vue
<template>
<ux-transition :show="show" name="fade" :duration="300">
<view class="card">
<text>过渡内容</text>
</view>
</ux-transition>
<ux-button text="切换显示" type="primary" shape="round" @click="show = !show" />
</template>
<script setup lang="uts">
const show = ref(true);
</script>预设动画 name
支持 fade / slide-up / slide-down / slide-left / slide-right / zoom-in / zoom-out 七种预设,点击切换并立即重播。
查看源码
vue
<template>
<!-- name 可选 fade / slide-up / slide-down / slide-left / slide-right / zoom-in / zoom-out -->
<ux-transition :show="show" :name="current" :duration="300">
<view class="card">
<text>过渡内容</text>
</view>
</ux-transition>
<ux-button text="重播动画" type="primary" shape="round" @click="replay" />
</template>
<script setup lang="uts">
const show = ref(true);
const current = ref('slide-up');
// 离场过渡结束后再进场,完成一次重播
const replay = () => {
show.value = false;
setTimeout(() => {
show.value = true;
}, 450);
};
</script>动画时长 duration
duration 设置进入与离开的过渡时长,单位毫秒。
查看源码
vue
<template>
<ux-transition :show="show" name="slide-up" :duration="duration">
<view class="card">
<text>过渡内容</text>
</view>
</ux-transition>
<ux-button text="重播动画" type="primary" shape="round" @click="replay" />
</template>
<script setup lang="uts">
const show = ref(true);
const duration = ref(300);
const replay = () => {
show.value = false;
setTimeout(() => {
show.value = true;
}, duration.value + 150);
};
</script>动画曲线 timing-function
timing-function 自定义缓动曲线,回弹曲线让动画更有弹性。
查看源码
vue
<template>
<ux-transition :show="show" name="zoom-in" :duration="500" :timing-function="timingFunction">
<view class="card">
<text>过渡内容</text>
</view>
</ux-transition>
</template>
<script setup lang="uts">
const show = ref(true);
// 默认曲线(标准);回弹曲线可取 cubic-bezier(0.175, 0.885, 0.32, 1.275)
const timingFunction = ref('cubic-bezier(0.2, 0.8, 0.2, 1)');
</script>动画延迟 delay
delay 设置过渡启动前的延迟,进入与离开都生效,完成事件在时长+延迟后触发。
查看源码
vue
<template>
<view class="row">
<text>延迟 (ms)</text>
<ux-number-box v-model="delay" :step="100" :min="0" :max="600" />
</view>
<ux-transition :show="show" name="slide-left" :duration="300" :delay="delay">
<view class="card">
<text>过渡内容</text>
</view>
</ux-transition>
</template>
<script setup lang="uts">
const show = ref(true);
const delay = ref(0);
</script>首次渲染动画 appear
appear=true 时组件首次挂载即播放进场动画;需重新挂载才能复现(外层 v-if 重建)。
查看源码
vue
<template>
<view class="row">
<text>首次渲染播放进场动画</text>
<ux-switch v-model="appear" />
</view>
<!-- 外层 v-if 重挂:appear 只在组件首次挂载时生效,重新挂载才能复现 -->
<view v-if="mounted">
<ux-transition :show="true" name="zoom-out" :duration="500" :appear="appear">
<view class="card">
<text>过渡内容</text>
</view>
</ux-transition>
</view>
<ux-button text="重新挂载" type="primary" shape="round" @click="remount" />
</template>
<script setup lang="uts">
const appear = ref(true);
const mounted = ref(true);
const remount = () => {
mounted.value = false;
setTimeout(() => {
mounted.value = true;
}, 50);
};
</script>事件回调
监听进出场全生命周期:before-enter / enter / after-enter / enter-cancelled / before-leave / leave / after-leave / leave-cancelled。
查看源码
vue
<template>
<ux-transition
:show="show"
name="slide-up"
:duration="400"
@before-enter="logEvent('before-enter')"
@enter="logEvent('enter')"
@after-enter="logEvent('after-enter')"
@enter-cancelled="logEvent('enter-cancelled')"
@before-leave="logEvent('before-leave')"
@leave="logEvent('leave')"
@after-leave="logEvent('after-leave')"
@leave-cancelled="logEvent('leave-cancelled')"
>
<view class="card">
<text>过渡内容</text>
</view>
</ux-transition>
<ux-button text="切换显示" type="primary" shape="round" @click="show = !show" />
<view class="log">
<text v-for="(item, index) in logs" :key="index">{{ item }}</text>
</view>
</template>
<script setup lang="uts">
const show = ref(true);
const logs = ref<string[]>([]);
const logEvent = (name: string) => {
logs.value = ([name] as string[]).concat(logs.value.slice(0, 7));
};
</script>自定义样式 custom-class / custom-style
custom-class 扩展根节点样式类,custom-style 内联自定义样式。
查看源码
vue
<template>
<ux-transition
custom-class="my-transition"
:custom-style="customStyle"
:show="show"
name="fade"
:duration="400"
>
<view class="card">
<text>过渡内容</text>
</view>
</ux-transition>
</template>
<script setup lang="uts">
const show = ref(true);
const customStyle = ref<UTSJSONObject>({
'background-color': '#edf4ff',
'border-radius': '8px'
});
</script>
<style scoped>
/* custom-class 外部类:为过渡根节点补充内边距 */
.my-transition {
padding: 12px;
}
</style>API
Props
| 属性 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
customStyle | 自定义根节点样式 | UTSJSONObject | - | - |
customClass | 自定义根节点样式类 | string | '' | - |
show | 是否展示(默认true) | Boolean | true | - |
name | 预设动画:fade/slide-up/slide-down/slide-left/slide-right/zoom-in/zoom-out(默认fade) | String | 'fade' | - |
duration | 进入/离开动画时长,单位ms(默认300) | Number | 300 | - |
timingFunction | 动画曲线(默认cubic-bezier(0.2,0.8,0.2,1)) | String | 'cubic-bezier(0.2, 0.8, 0.2, 1)' | - |
delay | 动画延迟,单位ms,进入与离开都生效(默认0) | Number | 0 | - |
appear | 首次渲染时是否播放进场动画(默认false) | Boolean | false | - |
Events
| 事件名 | 说明 | 回调参数 | 版本 |
|---|---|---|---|
before-enter | 开始进入 | - | - |
enter | 进入动画真正启动(挂载隔一拍切终态类后;重开场景与 before-enter 同拍) | - | - |
after-enter | 进入动画结束 | - | - |
enter-cancelled | 进入动画未完成即被离开打断 | - | - |
before-leave | 开始离开 | - | - |
leave | 离开动画启动(与 before-leave 同拍,预留) | - | - |
after-leave | 离开动画结束(DOM 已卸载) | - | - |
leave-cancelled | 离开动画未完成即被重进打断 | - | - |
Slots
| 插槽名 | 说明 | 版本 |
|---|---|---|
default | 过渡的内容(显隐时整体做进出场过渡) | - |
注意事项
appear只在组件首次挂载时生效,之后切换show不再播放进场动画;要复现需重建组件(外层v-if)。- 完成事件(
after-enter/after-leave)由duration + delay的定时器判定,不依赖transitionend(App 端可能不触发),与实际渲染帧可能有一拍偏差。 leave播完才卸载 DOM;进场途中切离场会派发enter-cancelled,离场途中重开会派发leave-cancelled。- 未知的
name会回退为fade。 - App 端
transition-duration/transition-delay不支持多值列表,故时长 / 延迟 / 曲线按单值内联下发,起始与终态属性由预设类提供。