在NextJS中实现带定时器循环逐个打开手风琴项及联动图片切换
Next.js 手风琴组件功能升级方案
需求概述
已完成基础手风琴组件开发,需实现两个核心功能:
- 自动按顺序循环打开手风琴项,支持自定义每个项的显示时长;
- 侧边图片与当前打开的手风琴项联动切换。
解决方案实现
1. 升级数据结构(新增图片字段)
先为每个手风琴项添加对应的图片路径,方便后续联动:
export const onboardData = [ { title: '需求沟通', description: '开启协作项目只需访问我们的网站,填写联系表单即可取得联系。我们会与您协作梳理项目范围,确定如何通过我们的服务为您提供支持。', duration: 5000, image: '/path/to/discovery-call.jpg' // 替换为实际图片路径 }, { title: '原型制作', description: '开启协作项目只需访问我们的网站,填写联系表单即可取得联系。我们会与您协作梳理项目范围,确定如何通过我们的服务为您提供支持。', duration: 15000, image: '/path/to/prototype-creation.jpg' }, { title: '设计与开发', description: '开启协作项目只需访问我们的网站,填写联系表单即可取得联系。我们会与您协作梳理项目范围,确定如何通过我们的服务为您提供支持。', duration: 10000, image: '/path/to/design-dev.jpg' }, { title: '模块测试', description: '开启协作项目只需访问我们的网站,填写联系表单即可取得联系。我们会与您协作梳理项目范围,确定如何通过我们的服务为您提供支持。', duration: 5000, image: '/path/to/testing-modules.jpg' }, { title: '上线发布', description: '开启协作项目只需访问我们的网站,填写联系表单即可取得联系。我们会与您协作梳理项目范围,确定如何通过我们的服务为您提供支持。', duration: 10000, image: '/path/to/launch.jpg' }, ];
2. 修改手风琴组组件(实现自动循环+图片联动)
在根组件中添加自动切换逻辑和图片展示区域:
'use client' import { useState, useEffect, useRef } from 'react' import OnboardItem from './OnboardItem' import { onboardData } from './onboardData' const AccordionGroup = () => { const [isOpen, setIsOpen] = useState(0) const [isAutoPlaying, setIsAutoPlaying] = useState(true) const timerRef = useRef<NodeJS.Timeout | null>(null) // 手动切换时暂停自动播放 const toggleOpen = (id: number) => () => { setIsOpen(id) setIsAutoPlaying(false) timerRef.current && clearTimeout(timerRef.current) } // 自动循环切换逻辑 useEffect(() => { if (!isAutoPlaying) return const nextIndex = (isOpen + 1) % onboardData.length timerRef.current = setTimeout(() => { setIsOpen(nextIndex) }, onboardData[isOpen].duration) // 清理定时器,防止内存泄漏 return () => timerRef.current && clearTimeout(timerRef.current) }, [isOpen, isAutoPlaying]) return ( <div className='flex gap-8'> {/* 侧边联动图片区域 */} <div className='flex-1 overflow-hidden rounded-lg'> <img src={onboardData[isOpen].image} alt={onboardData[isOpen].title} className='w-full h-full object-cover transition-opacity duration-700' /> </div> {/* 手风琴项列表 */} <div className='flex-1 space-y-6'> {onboardData.map(({ title, description, duration }, index) => ( <OnboardItem key={index} title={title} description={description} duration={duration} isOpen={isOpen === index} toggle={toggleOpen(index)} /> ))} </div> </div> ) } export default AccordionGroup
3. 优化手风琴项组件(类型规范)
为组件props添加明确的类型定义,提升代码健壮性:
'use client' interface OnboardItemProps { title: string description: string duration: number isOpen: boolean toggle: () => void } const OnboardItem = ({ title, description, isOpen, toggle }: OnboardItemProps) => { return( <div className='relative'> <div className='w-0.5 bg-neutral-300 dark:bg-neutral-500 absolute left-0 top-0 bottom-0'></div> <div className='ps-5 items-center'> <p className={`text-2xl leading-[38px] select-none cursor-pointer ${isOpen ? 'text-black dark:text-primary' : 'text-neutral-400 dark:text-neutral-300'}`} onClick={toggle}>{title}</p> <div className={`grid mt-1 overflow-hidden ease-in-out ${isOpen ? 'accordion-animate-open pb-1' : 'accordion-animate'}`}> <div className='leading-7 min-h-0'><p className='select-none'>{description}</p></div> </div> </div> </div> ) } export default OnboardItem
关键实现说明
- 自动循环逻辑:通过
useEffect监听当前打开项索引,利用setTimeout设置下一个切换时间,手动点击时暂停自动播放避免冲突; - 图片联动:根据当前打开项的索引直接渲染对应图片,添加CSS过渡实现平滑切换效果;
- 定时器管理:用
useRef保存定时器ID,组件卸载或状态变化时清理定时器,防止内存泄漏; - 类型规范:为组件props添加TypeScript接口,避免类型错误。
内容的提问来源于stack exchange,提问作者Ajinkya More
相关产品推荐
相关产品推荐

