如何在Material-UI可滚动Tabs组件中自定义滚动箭头SVG图标
自定义可滚动Tabs滚动按钮的正确实现逻辑
先拆解你当前代码失效的核心原因
ScrollButtonComponent属性接收的是React组件类型本身,不是执行后返回的JSX节点,你当前把组件当函数调用传值的方式本身不符合规范- 你写的
scrollButton组件硬编码了direction="right",完全没有消费Tabs内部自动注入的方向属性,导致左右两个滚动按钮无法区分 - 图标渲染方式错误:直接把
CloseIcon组件引用作为子节点传入,没有渲染为可识别的React元素 - 额外包裹的无意义div会破坏TabScrollButton本身的布局定位,导致按钮位置偏移
- 不需要为左右两个方向单独创建两套自定义组件,Tabs会在渲染按钮时自动注入方向属性,同一个组件内做条件渲染即可适配。
ScrollButtonComponent的官方使用规范
这个属性本质是让你替换Tabs内置的滚动按钮实现,传入组件后,Tabs会自动给你写的组件注入4个核心props,你不需要自己处理滚动逻辑:
direction:标识按钮对应的滚动方向,水平布局下值为left/right,垂直布局下为up/downorientation:标识Tabs整体布局方向,值为horizontal/verticaldisabled:标识按钮是否为禁用状态(当滚动到Tabs两端无内容可滑动时,会自动设为true)onClick:内置的滚动触发方法,直接透传给按钮元素即可实现点击滚动,不需要自己写滚动逻辑。
*最省心的实现方式是基于官方TabScrollButton二次封装,只替换内部图标部分,不需要重写全部交互逻辑。
修正后的完整可运行代码
import Tab from '@material-ui/core/Tab'; import Tabs from '@material-ui/core/Tabs'; import TabScrollButton from '@material-ui/core/TabScrollButton'; // 引入你自己的自定义图标组件 import { CloseIcon } from 'app/components/atoms/icons'; // 把自定义滚动按钮抽离到组件外部,避免内联导致Tabs反复重建组件 const CustomScrollButton = (props) => { // 解构出方向属性,其余属性全部透传给官方TabScrollButton const { direction, ...restProps } = props; return ( <TabScrollButton {...restProps}> {/* 单图标场景下根据方向旋转即可,不需要做两套图标 */} <CloseIcon style={direction === 'left' ? { transform: 'rotate(180deg)' } : {}} /> </TabScrollButton> ); }; const MyCarousel = ({ value }: Props) => { return ( <div css={styles.root}> <Tabs value={value} indicatorColor="primary" variant="scrollable" scrollButtons="auto" aria-label="scrollable auto tabs example" {/* 直接传组件类型,不要加括号执行 */} ScrollButtonComponent={CustomScrollButton} > <Tab label="Item One" /> <Tab label="Item Two" /> <Tab label="Item Three" /> <Tab label="Item 4" /> <Tab label="Item 5" /> <Tab label="Item 6" /> <Tab label="Item 7" /> <Tab label="Item 8" /> <Tab label="Item 9" /> </Tabs> </div> ); }; export default MyCarousel;
几个实用注意点
- 如果使用两个独立的左右箭头图标,直接根据
direction值做条件渲染即可,不需要拆分两个独立的按钮组件 - 不要把自定义滚动按钮写成内联箭头函数直接放在Tabs属性里,每次组件重渲染都会生成新的组件类型,会导致Tabs反复卸载重建按钮,出现滚动逻辑失效、按钮闪烁的问题
- 如果不需要保留官方TabScrollButton的默认样式,完全可以从头写按钮结构,只需要把props里的
onClick、disabled属性透传到你自己的按钮元素上即可,不需要额外实现滚动逻辑。
内容的提问来源于stack exchange,提问作者meez
相关产品推荐
相关产品推荐

