原生js实现带左右箭头可滑动的tab效果

效果如下:

请添加图片描述
由于分辨率的问题,在起始位置的的左箭头和末尾位置的右箭头禁用状态没有录上,其实是有的。

布局分析

在这里插入图片描述
总的来说,将用三个盒子来实现效果:
可视区域为黄色框①,包含可视tab蓝色框②以及左右箭头红色框;
绿色框③就是所有的tab了,②和③的关系就是卡槽和卡带的关系。

内容设计

我项目引用的是ant design vue库,所以整个都是基于库内的组件进行讲解的,但是其他库也是相似的,如有问题请留言反馈

方便控制左右按钮的禁用状态设置,我采用button组件的图标按钮

<div class="menu-tab">
	<a-button
		v-if="show"  //实际应用中若是tab较少则没有显示箭头的必要(会在mounted中进行判断)
		icon="left"
		type="link"
		ghost
		:disabled="disabled1"
		style="
			width: 20px;
			height: 20px;
			position: absolute;
			top: 38%;
			left: 0;
		"
		@click="toPrev"
	/>
	<div class="activemenu">
		<div class="active-menu-animated">
			<span
				:key="index"
				v-for="(item, index) in menuData"
				@click="menuClick(index)"
				:class="index == activeKey1 ? 'active-span' : ''"  //控制选中tab的活性状态
			>
			tab{{ index + 1 }}
			</span>
		</div>
	</div>
	<a-button
		v-if="show"
		icon="right"
		type="link"
		ghost
		:disabled="disabled2"
		style="
			width: 20px;
			height: 20px;
			position: absolute;
			top: 38%;
			right: 0;
		"
		@click="toNext"
	/>
</div>

处理方案

1、data

设置一些默认值

show: false,
disabled1: true,
disabled2: false,

2、mounted

控制菜单tab左右箭头的显隐

  mounted() {
  	//蓝盒子2的内容区域宽度
    let e1 = document.getElementsByClassName("activemenu")[0].clientWidth;
    //绿盒子3的内容区域宽度
    let e2 = document.getElementsByClassName("active-menu-animated")[0].clientWidth;
    if (e1 < e2) {
      this.show = true;
    }
  },

3、methods

左箭头
    toPrev() {
      this.disabled2 = false;//右箭头禁用解开
      let ele = document.getElementsByClassName("active-menu-animated")[0];
      //由于获取到的left是带有单位的,不能直接运算,所以要想办法得到数值再组合单位进行赋值
      //使用三目运算符的目的是最开始的时候得到元素的left是undefined,可是不能直接进行运算的哟
      ele.style.left = ele.style.left.split("p")[0]
        ? Number(ele.style.left.split("p")[0]) + 300 + "px"
        : "300px";
      //判断平移位置,左箭头禁用
      if (ele.style.left.split("p")[0] == 0) {
        this.disabled1 = true;
      }
    },
右箭头
    toNext() {
      this.disabled1 = false;//左箭头禁用解开
      let ele = document.getElementsByClassName("active-menu-animated")[0];
      //解释同上
      ele.style.left = ele.style.left.split("p")[0]
        ? ele.style.left.split("p")[0] - 300 + "px"
        : "-300px";
      //判断平移位置,右箭头禁用
      if (Math.abs(ele.style.left.split("p")[0]) + 300 > ele.clientWidth) {
        this.disabled2 = true;
      }
    },

样式设置

1、menu-tab

.menu-tab{
	padding: 0 20px;
	position: relative;
	font-size: 20px;
	color: #fff;
	overflow: hidden;
}

2、activemenu

  .activemenu {
    padding: 0 20px;
    overflow: hidden;
    white-space: nowrap;
    span {
      padding: 0 20px;
      cursor: pointer;
    }
    span:hover,
    .active-span {
      color: #ffffff;
      padding-bottom: 24px;
      border-bottom: 3px solid #fff;
      font-weight: bold;
    }
  }

3、active-menu-animated

  .active-menu-animated {
    position: relative;
    display: inline-block;
    box-sizing: border-box;
    margin: 0;
    padding-left: 0;
    list-style: none;
    transition: left 0.3s ease-in-out;
  }

整体效果

1、较少tab

在这里插入图片描述

2、多个tab

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值