如何用Vue实现Svelte中Deferred transitions同款过渡效果?
用Vue的Transition/TransitionGroup实现Svelte Deferred同款过渡效果
先看目标效果:
这个效果的核心是点击元素展开时,其他元素按顺序延迟位移/收缩,形成连贯的层级过渡。Vue没有原生的deferred transitions,但可以通过「自定义过渡延迟+TransitionGroup的钩子」来实现,以下是完整实现方案:
核心思路
- 用CSS变量给每个列表项绑定基于索引的过渡延迟,实现依次触发的效果
- 通过动态修改元素高度(或内部内容的显隐)触发过渡
- 配合TransitionGroup处理列表项的进入/离开过渡,调整延迟顺序让动画更自然
完整代码实现
组件模板
<template> <div class="container"> <TransitionGroup name="deferred" tag="div" class="list"> <div v-for="(item, index) in items" :key="item.id" class="list-item" :style="{ '--delay': index * 50 + 'ms', '--height': activeId === item.id ? '120px' : '40px' }" @click="activeId = activeId === item.id ? null : item.id" > {{ item.text }} <!-- 可添加展开后的自定义内容 --> <div v-if="activeId === item.id" class="expanded-content"> 展开的详细内容 {{ item.id }} </div> </div> </TransitionGroup> </div> </template>
脚本逻辑
<script setup> import { ref } from 'vue' // 模拟列表数据 const items = ref([ { id: 1, text: 'Item 1' }, { id: 2, text: 'Item 2' }, { id: 3, text: 'Item 3' }, { id: 4, text: 'Item 4' }, { id: 5, text: 'Item 5' } ]) // 记录当前展开的项ID const activeId = ref(null) </script>
样式部分(关键)
<style scoped> .container { width: 300px; margin: 2rem auto; } .list { display: flex; flex-direction: column; gap: 0.5rem; } .list-item { background: #42b883; color: #fff; border-radius: 4px; padding: 0 1rem; height: 40px; display: flex; flex-direction: column; justify-content: center; cursor: pointer; /* 核心过渡属性:高度、间距的平滑变化 */ transition: height 0.3s ease, margin 0.3s ease; /* 绑定自定义延迟变量 */ transition-delay: var(--delay); overflow: hidden; } .expanded-content { padding: 0.5rem 0; font-size: 0.875rem; } /* TransitionGroup 处理列表项的进入/离开动画 */ .deferred-enter-from, .deferred-leave-to { opacity: 0; transform: translateY(10px); } .deferred-enter-active, .deferred-leave-active { transition: opacity 0.3s ease, transform 0.3s ease; transition-delay: var(--delay); } /* 离开时反向延迟,让后面的元素先收缩,和Svelte deferred行为一致 */ .deferred-leave-active { transition-delay: calc(250ms - var(--delay)); } </style>
关键细节说明
- 延迟计算:用
index * 50ms给每个元素设置递增延迟,数值可根据需求调整,越大过渡间隔越明显 - 反向延迟:离开动画使用
calc(250ms - var(--delay)),让索引大的元素先开始收缩,避免动画重叠混乱 - 内容扩展:如果需要更复杂的展开内容,只需在列表项内部添加动态显隐的元素,配合
overflow: hidden即可,过渡逻辑不变
内容的提问来源于stack exchange,提问作者Pavan Kumar
相关产品推荐
相关产品推荐

