React轮播组件transition过渡效果仅首次加载生效点击切换失效求助
问题核心原因
- 现有实现仅渲染与当前
selectedIndex匹配的单张轮播图,切换索引时会直接销毁旧的section元素、创建全新的section元素。CSS transition的触发前提是同一个DOM元素的可过渡属性发生变化,新创建的元素挂载时就已经携带transition类和最终样式,没有属性变化的过程,因此只有首次挂载时会触发动画,后续切换均无过渡效果。 - 附加小问题:
previous、next函数的判断逻辑为并行双if,写法冗余,可简化。
修复方案
1. 调整渲染逻辑
不再过滤仅展示当前选中的轮播图,改为全量渲染所有轮播图,通过动态类名控制当前展示项的样式,利用同一个DOM元素的属性变化触发过渡。
2. 优化状态更新逻辑
用取模运算简化首尾切换的判断代码。
3. 补充对应CSS规则
定义过渡属性、时长,以及选中/未选中状态的样式差异。
修复后代码参考
import { useState } from 'react'; const SlideShowTop = (props) => { const [selectedIndex, setSelectedIndex] = useState(0); const previous = () => { setSelectedIndex(prev => (prev - 1 + props.slides.length) % props.slides.length); }; const next = () => { setSelectedIndex(prev => (prev + 1) % props.slides.length); }; const sliderList = props.slides.map((slideProp, index) => { const getImg = require("../assets/" + slideProp.picture).default; // 动态绑定类名:始终有过渡类,选中时额外加激活类 const sectionClass = `${classes.transitions} ${index === selectedIndex ? classes.active : ''}`; return ( <section key={slideProp.index} className={sectionClass}> <li className={classes.banner} style={{ backgroundImage: `url(${getImg})`, }} > <div className={classes.banner__contents}> <h1 className={classes.banner__title}> {slideProp.title} </h1> <div className={classes["ty-seqHomeSlider-nav"]}> <button onClick={previous} type="button" className={classes["seq-prev"]} > <i className="fa fa-angle-left" style={{ color: "white" }} aria-hidden="true" ></i> </button> <button onClick={next} type="button" className={classes["seq-next"]}> <i className="fa fa-angle-right" style={{ color: "white" }} aria-hidden="true" ></i> </button> </div> <h1 className={classes.banner__description}> {slideProp.overview} </h1> </div> <div className={classes.banner_fadeBottom}></div> </li> </section> ); }); return ( <div> <ul>{sliderList}</ul> </div> ); }; export default SlideShowTop;
对应CSS参考示例(可根据过渡需求自行调整)
/* 轮播项公共样式 */ .transitions { position: absolute; top: 0; left: 0; width: 100%; /* 定义过渡属性和时长 */ transition: all 0.5s ease; /* 非激活状态默认透明+右移 */ opacity: 0; transform: translateX(100%); } /* 激活状态完全显示+原位 */ .transitions.active { opacity: 1; transform: translateX(0); } /* 父容器需要加相对定位,容纳绝对定位的轮播项 */ ul { position: relative; overflow: hidden; /* 自行设置高度匹配轮播图尺寸 */ height: 400px; padding: 0; margin: 0; }
内容的提问来源于stack exchange,提问作者sinfulexiled
相关产品推荐
相关产品推荐

