FAQ页面外部锚点链接触发Accordion滚动并展开的问题
解决外部锚点链接进入FAQ页面时折叠面板不展开的问题
问题描述
当前FAQ页面内点击折叠面板标题时,URL会自动更新为对应锚点格式(如localhost:3000/faq#title-of-question),且面板能正常展开;但通过外部带锚点的链接(如localhost:3000/faq#why-choose-us)进入页面时,页面仅能滚动到对应元素,面板无法自动展开。
解决方案
通过管理折叠面板的展开状态,并监听URL哈希变化,实现初始加载和哈希变更时的面板自动展开:
- 引入状态管理与监听逻辑
在组件中添加useState维护展开状态,通过useEffect监听初始加载和哈希变化事件:
import { useState, useEffect } from 'react'; // ... 其他导入 const FAQPage = () => { const [expanded, setExpanded] = useState<string | false>(false); useEffect(() => { const handleHashChange = () => { const hash = window.location.hash.slice(1); // 移除URL中的#符号 if (hash) { setExpanded(hash); // 滚动到目标元素 const targetElement = document.getElementById(hash); targetElement?.scrollIntoView({ behavior: 'smooth' }); } else { setExpanded(false); } }; // 组件加载时执行一次,处理初始锚点 handleHashChange(); // 监听URL哈希变化 window.addEventListener('hashchange', handleHashChange); // 组件卸载时移除监听 return () => window.removeEventListener('hashchange', handleHashChange); }, []); // ... 其他代码 };
- 修改Accordion组件配置
更新折叠面板的属性,绑定展开状态和交互事件,同时移除原有的<a>标签避免冲突:
{data.elements.map((feature, index) => ( <Accordion id={`${feature.slug}`} key={index} expanded={expanded === feature.slug} onChange={() => { const newExpanded = expanded === feature.slug ? false : feature.slug; setExpanded(newExpanded); // 同步更新URL哈希 if (newExpanded) { window.location.hash = newExpanded; } else { // 折叠时移除哈希 window.history.pushState('', document.title, window.location.pathname); } }} > <AccordionSummary expandIcon={<Iconify icon={ExpandMoreIcon} />} aria-controls={`panel-content-${index}`} id={`panel-header-${index}`} > <Typography sx={{ fontWeight: 600 }}>{feature.title}</Typography> </AccordionSummary> <AccordionDetails> <Typography>{feature.description}</Typography> </AccordionDetails> </Accordion> ))}
逻辑说明
- 状态
expanded记录当前展开的面板slug,false表示无面板展开。 useEffect在组件初始化时检查URL哈希,若存在对应面板则自动展开并滚动到目标位置;同时监听哈希变化,确保用户手动修改URL或页面内跳转时同步更新面板状态。Accordion的expanded属性控制面板展开状态,onChange事件处理点击交互,同步更新URL哈希值,保持页面状态与URL一致。
内容的提问来源于stack exchange,提问作者Free Me
相关产品推荐
相关产品推荐

