效果如图

添加Tabs的id,防止一页多个Tabs

const tabsDivId = useRef(Math.random());
<Tabs id={tabsDivId.current}>{children}</Tabs>

当 Tabs 的标签页总长度超过可现实区域长度,出现左右箭头,否则不显示

const [navHeight,setNavHeight] = useState(0);
useEffect(() => {const tabListWidth = document.getElementById(tabsDivId.current).children[0].children[0].children[0].clientWidth;const tabsNavWidth = document.getElementById(tabsDivId.current).children[0].clientWidth;if(tabListWidth-tabsNavWidth > 0){setShowArrow(true)}setNavHeight(document.getElementById(tabsDivId.current).children[0].clientHeight)
},[])

将箭头样式添加到 Tabs 组件上,并且绑定点击事件

使用 useEffect ,页面渲染完成之后添加左右箭头样式,这里左右箭头宽度各20px,重新计算出标签页总宽度

useEffect(() => {if(showArrow && showTabsArrow ){// tab父元素const tabDiv = document.getElementById(tabsDivId.current).children[0];// 标签const tabNavDiv = tabDiv.children[0];tabNavDiv.style.width = 'calc( 100% - 40px )'// 内容const tabContentDiv = tabDiv.children[1];const leftArrow = document.createElement('button');leftArrow.style = 'width:20px;height:' + navHeight + 'px' + ';text-align:center;line-height:' + (navHeight-10)+'px' + ';border:none;font-size:20px;padding:0;cursor: pointer;'leftArrow.innerHTML = "<";leftArrow.addEventListener('click',(e) => leftButton(e))tabDiv.insertBefore(leftArrow,tabNavDiv)const rightArrow = document.createElement('button');rightArrow.style = 'width:20px;height:' + navHeight + 'px' + ';text-align:center;line-height:' + (navHeight-10)+'px'+';border:none;font-size:20px;padding:0;cursor: pointer;';rightArrow.innerHTML='>';rightArrow.addEventListener('click',(e) => rightButton(e))tabDiv.insertBefore(rightArrow,tabContentDiv)}},[showArrow])

点击箭头实现滚动效果,左右箭头同理,以右箭头为例

计算偏移量,使的右侧箭头不遮挡 Tabs 标签页内容
更改 Tabs 的 cssText 以实现滚动效果

const rightButton = (e) => {const tabList = document.getElementById(tabsDivId.current).children[0].children[1].children[0];const tabsNav = document.getElementById(tabsDivId.current).children[0];// 计算偏移量const offset = type == 'editable-card' ? 0 : (type == 'card' ? (tabList.children[tabList.children.length-2].clientWidth)/2 : tabList.children[tabList.children.length-2].clientWidth) ;if(tabList.clientWidth > tabsNav.clientWidth){const translateX = Number(tabList.style.cssText.split('px')[0].split('(')[1])-100;if(Math.abs(translateX) < (tabList.clientWidth - tabsNav.clientWidth)){tabList.style.cssText = 'transform: translate(' + translateX +'px, 0px);'}else{tabList.style.cssText = 'transform: translate(' + -(tabList.clientWidth - tabsNav.clientWidth + offset ) +'px, 0px);'}}
}

相关内容完整代码

const tabsDivId = useRef(Math.random());const [showArrow,setShowArrow] = useState(false);
const [navHeight,setNavHeight] = useState(0);// 右箭头点击事件
const rightButton = (e) => {const tabList = document.getElementById(tabsDivId.current).children[0].children[1].children[0];const tabsNav = document.getElementById(tabsDivId.current).children[0];// 计算偏移量const offset = type == 'editable-card' ? 0 : (type == 'card' ? (tabList.children[tabList.children.length-2].clientWidth)/2 : tabList.children[tabList.children.length-2].clientWidth) ;if(tabList.clientWidth > tabsNav.clientWidth){const translateX = Number(tabList.style.cssText.split('px')[0].split('(')[1])-100;if(Math.abs(translateX) < (tabList.clientWidth - tabsNav.clientWidth)){tabList.style.cssText = 'transform: translate(' + translateX +'px, 0px);'}else{tabList.style.cssText = 'transform: translate(' + -(tabList.clientWidth - tabsNav.clientWidth + offset ) +'px, 0px);'}}
}// 左箭头点击事件
const leftButton = (e) => {const tabList = document.getElementById(tabsDivId.current).children[0].children[1].children[0];const tabsNav = document.getElementById(tabsDivId.current).children[0];if(tabList.clientWidth > tabsNav.clientWidth){const translateX = Number(tabList.style.cssText.split('px')[0].split('(')[1])+100;if(Math.abs(translateX) < (tabList.clientWidth - tabsNav.clientWidth) && translateX < 0){tabList.style.cssText = 'transform: translate(' + translateX +'px, 0px);'}else{tabList.style.cssText = 'transform: translate(' + 0 +'px, 0px);'}}
}useEffect(() => {// 所有tabs标签宽度const tabListWidth = document.getElementById(tabsDivId.current).children[0].children[0].children[0].clientWidth;// tabs 可视区域宽度const tabsNavWidth = document.getElementById(tabsDivId.current).children[0].clientWidth;if(tabListWidth-tabsNavWidth > 0){setShowArrow(true)}setNavHeight(document.getElementById(tabsDivId.current).children[0].clientHeight)
},[])useEffect(() => {// DOM 结构详情可见 antd 的 tabs // tab父元素const tabDiv = document.getElementById(tabsDivId.current).children[0];// Tabs 宽度const tabNavDiv = tabDiv.children[0];tabNavDiv.style.width = 'calc( 100% - 40px )'// 内容const tabContentDiv = tabDiv.children[1];// 左侧箭头const leftArrow = document.createElement('button');leftArrow.style = 'width:20px;height:' + navHeight + 'px' + ';text-align:center;line-height:' + (navHeight-10)+'px' + ';border:none;font-size:20px;padding:0;cursor: pointer;'leftArrow.innerHTML = "<";leftArrow.addEventListener('click',(e) => leftButton(e))tabDiv.insertBefore(leftArrow,tabNavDiv);// 右侧箭头const rightArrow = document.createElement('button');rightArrow.style = 'width:20px;height:' + navHeight + 'px' + ';text-align:center;line-height:' + (navHeight-10)+'px'+';border:none;font-size:20px;padding:0;cursor: pointer;';rightArrow.innerHTML='>';rightArrow.addEventListener('click',(e) => rightButton(e))tabDiv.insertBefore(rightArrow,tabContentDiv)
},[])return (<Tabs id={tabsDivId.current}>{children}</Tabs>
)

基于antd,实现有左右箭头的Tabs相关推荐

  1. 支持大数据渲染下拉列表组件开发 SuperSelect(基于antd Select)

    功能简介 antd 的 Select 组件不支持大数据量的下拉列表渲染,下拉列表数量太多会出现性能问题, SuperSelect 基于 antd 封装实现,替换原组件下拉列表,只渲染几十条列表数据,随 ...

  2. 基于antd DatePicker的年份组件

    最近在开发的时候,发现antd的datepicker组件,设置mode="year"时候,年份组件交互上有一些bug问题,后来自己基于antd上的picker,进行了改装,能进行年 ...

  3. 【React 】基于Antd Design的Upload图片墙组件封装

    最近在统一UI组件库,基于项目的需求,封装了一个专门用来上传图片的控件,主要有以下一些功能: a. 可以动态配置保存的方式,可以上传到文档库.Redis缓存以及base64保存在数据库中: b. 动态 ...

  4. java antd实现登录,基于 antd pro 的短信验证码登录

    概要 整体流程 前端 页面代码 请求验证码和登录的 service (src/services/login.js) 处理登录的 model (src/models/login.js) 后端 短信验证码 ...

  5. 基于antd pro框架,配置接口apiUrl前缀

    基于antd-pro框架,配置package.json中的打包命令,实现不同环境使用不同的接口apiUrl前缀,避免人肉修改,保证各环境对应各自的api地址. 背景 这阵子,在玩antd-pro,感觉 ...

  6. 基于Antd Input组件自定义Input的成功状态

    前言 Ant Design的Input组件的有一个状态的Api 需求 公司自研UI组件,在Antd的基础上进行开发.其中Input组件除了警告与错误状态外,还增加了成功的状态.如下图⬇️ 开发实现 方 ...

  7. React基于antd Table实现可拖拽调整列宽的表格

    实现功能 1:表格列宽初始自动分配.列宽总和不能超过容器宽度(无横向滚动条,公司项目特殊需求) 2:当容器宽度变化时,保持当前列宽的分配比例,等比缩小 3:拖动过程中不进行列宽的调整,只有释放之后再进 ...

  8. [html5技术]基于bootstrap制作的多标签页(tabs)#1024程序员福音来了

    下载地址 点击下载 效果图 default/默认 (带有向左.向右移动以及选项菜单) 参考Demo: nav-tabs and nav-pills classic/折叠 (折叠隐藏tab) 作用与优势 ...

  9. antd 能自适应吗_react 基于antd表格自适应宽度显示。。。鼠标滑动显示详细内容解决办法...

    最终效果内容如下 创建公共组件获取表格宽度 class EllipsisTooltip extends React.Component { constructor(props){ super(prop ...

最新文章

  1. 分类问题的评估指标(Evaluation for Classifier)
  2. Laravel+Angularjs+D3打造可视化数据,RESTful+Ajax
  3. 编程之美-数组分割方法整理
  4. 新电子书:解决生产中Java应用程序错误的完整指南
  5. 褚时健:现在的年轻人太急了,我快90了还在摸爬滚打
  6. jupyter显示dataframe完整的行与列
  7. vue element form ref 重置表单
  8. 一次linux root密码错修改历程
  9. Python——Pycharm基本设置
  10. 《周一清晨的领导课》--司机与乘客 - [读书笔记]
  11. 装饰器+依赖注入开发node后台接口
  12. Wibbitz:根据网页文字生成在线视频(转)
  13. 【毕设记录】第一篇:开题,整体App计划
  14. Docker 容器监控原理及 cAdvisor 的安装与使用
  15. 2016-2017 7th BSUIR Open Programming Contest. Final 补题
  16. 【自学】C语言程序设计
  17. 企业微信脚手架(企业内部)
  18. scrapy-爬取百度贴吧之物流内容。
  19. Unicode和GB的转换库和UrlEncode和getSpell函数
  20. mysql 中自增的起始值和步长_MySQL设置自增初始值和步长

热门文章

  1. 形象理解线性代数(一)——什么是线性变换?
  2. android 下载apk并自动安装,Android下载apk并自动安装(兼容Android7.0)
  3. 万向区块链元宇宙系列报告:对工业元宇宙的认知
  4. php emoji过滤,php + js 移动端 过滤emoji表情符号 完美解决
  5. Python登录注册页面(用字符串,组合数据类型,程序三种基本结构)
  6. python爬取京东书籍_Python爬取当当、京东、亚马逊图书信息代码实例
  7. 钢铁行业电商平台架构解决方案
  8. Java毕设项目学校旧书交易网站计算机(附源码+系统+数据库+LW)
  9. stream relocation truncated to fit
  10. 几点需要注意选择APP开发外包团队的注意事项