React/Typescript+Emotion实现水平菜单激活按钮自动滚动到视口方案咨询
实现方案
核心思路
利用浏览器原生Element.scrollIntoView()API,在按钮激活时自动滚动到可视区域,无需额外引入第三方库。
具体修改步骤
1. 先修正容器样式笔误
你提供的StyledDiv样式中overflow: auto后缺少分号,会导致后续样式失效,先补上:
const StyledDiv = withTheme( styled.div<StyledProps>` display: flex; flex-wrap: nowrap; overflow: auto; width: 100%; overflow-x: scroll; overflow-y: hidden; column-gap: 8px; -webkit-overflow-scrolling: touch; &::-webkit-scrollbar { display: none; } ` )
2. 修改按钮组件,添加滚动逻辑
在按钮组件内引入useRef和useEffect,监听isActive状态,激活时触发滚动:
import { useRef, useEffect } from 'react'; // 组件内部逻辑 const buttonRef = useRef<HTMLButtonElement>(null); // 监听激活状态,触发滚动 useEffect(() => { if (isActive && buttonRef.current) { buttonRef.current.scrollIntoView({ behavior: 'smooth', // 平滑滚动,不需要动画可以设为'auto' block: 'nearest', // 垂直方向不滚动 inline: 'nearest' // 水平方向滚动到刚好完全可见的位置,如果要滚动到视口中间可以改成'center' }); } }, [isActive]); return ( <Button ref={buttonRef} data-label={label} isActive={isActive} onClick={() => setActiveCategory(cat)} > { renderIcon(icon) } <Wrapper> {label} <StyledSpan isActive={isActive}>{label}</StyledSpan> </Wrapper> </Button> )
注意事项
- Emotion的styled生成的原生元素组件默认支持ref透传,无需额外做
forwardRef处理 - 如果需要兼容非常旧的移动端浏览器,可以把
scrollIntoView替换为scrollIntoViewIfNeeded,两者效果基本一致 - 若你的按钮是封装在其他自定义函数组件内,需要手动通过
forwardRef转发ref到实际的button DOM元素上
内容的提问来源于stack exchange,提问作者Baldini
相关产品推荐
相关产品推荐

