效果如图
添加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>
)