如何使用React实现列表项按顺序逐次入场显示的效果?
解决方案
你遇到的问题核心原因是map为同步遍历方法,所有卡片会同时被插入DOM触发入场动画,自然会同时出现,这里提供两种常用实现方案:
方案1:CSS延迟控制(实现最简单)
利用索引为每个卡片的入场动画设置递增延迟,无需修改JS逻辑,仅需改动两处代码:
- 遍历
milestones时拿到元素索引,为卡片容器添加内联延迟样式
return ( <TransitionGroup className='listOfMilestones'> {milestones.map((milestone, index) => { return ( <CSSTransition key={milestone.id} timeout={500} classNames='eachMilestone' > {/* 按索引添加延迟,300为两个卡片入场的间隔时间,可自行调整 */} <div style={{transitionDelay: `${index * 300}ms`}}> <MilestoneCard ageRange={ageRange} id={milestone.id} title={milestone.title} answer={milestone.answer} /> </div> </CSSTransition> }) } </TransitionGroup> )
- 修改CSS确保延迟属性生效:
.eachMilestone-enter { opacity: 0.01; transform: translateY(40px); } .eachMilestone-enter-active { opacity: 1; transform: translateY(0px); /* 加上all确保延迟对所有过渡属性生效 */ transition: all 500ms ease-in; }
方案2:状态控制逐个挂载(可控性更高)
如果需要元素真的按顺序逐个挂载进DOM(适合长列表优化),可以通过状态控制显示的卡片列表:
- 新增状态和定时器逻辑:
import { useState, useEffect } from 'react'; // 组件内逻辑 const [visibleMilestones, setVisibleMilestones] = useState([]); useEffect(() => { const timers = []; // 逐个向显示列表添加元素 milestones.forEach((item, index) => { const timer = setTimeout(() => { setVisibleMilestones(prev => [...prev, item]); }, index * 300); // 300为添加间隔,可自行调整 timers.push(timer); }) // 组件卸载时清空定时器,避免内存泄漏 return () => timers.forEach(timer => clearTimeout(timer)); }, [milestones]);
- 渲染时遍历受控的显示列表即可:
return ( <TransitionGroup className='listOfMilestones'> {visibleMilestones.map((milestone) => { return ( <CSSTransition key={milestone.id} timeout={500} classNames='eachMilestone' > <MilestoneCard ageRange={ageRange} id={milestone.id} title={milestone.title} answer={milestone.answer} /> </CSSTransition> }) } </TransitionGroup> )
内容的提问来源于stack exchange,提问作者byte03
相关产品推荐
相关产品推荐

