uni-app 自定义 tab 切换组件

一、可横向滑动的 tab

效果图:
在这里插入图片描述

实现:
封装组件:

<template>
  <view class="content">
    <view class="hand">
      <scroll-view scroll-x="true" class="scroll-class">
        <view class="dataInfo">
          <view
            class="dataList"
            v-for="(item, index) in tabList"
            :key="index"
            @click="changeTab(index)"
          >
            <view :class="tabIndex == index ? 'activite' : ''" class="name">{{
              item.label
            }}</view>
            <view :class="tabIndex == index ? 'active-line' : ''"></view>
          </view>
        </view>
      </scroll-view>
    </view>
  </view>
</template>
 
<script>
export default {
  name: "baseTab",
  props: {
    tabList: {
      type: Array,
      default: () => [],
    },
    tabIndex: {
      type: Number,
      default: 0,
    },
  },
  data() {
    return {};
  },
  methods: {
    changeTab(index) {
      this.$emit("changeTab", index);
    },
  },
};
</script>
 
<style lang="less" scoped>
.content {
  .hand {
    .dataInfo {
      display: flex;
      text-align: center;
      width: 100%;
      .dataList {
        .name {
          font-size: 28rpx;
          color: #bdbdbd;
          display: block;
          line-height: 52rpx;
          width: 152rpx;
        }
        .name.activite {
          color: #333333;
        }
        .active-line {
          height: 6rpx;
          width: 100rpx;
          background: #3ec3ae;
          border-radius: 2rpx;
          margin: 0 auto;
        }
      }
    }
  }
  .scroll-class {
    white-space: nowrap;
    border-bottom: 2rpx solid #e1e4e6;
  }
}
</style>

页面调用:

<base-tab :tabIndex="tabIndex" :tabList="tabList" @changeTab="changeTab" ></base-tab>
export default{
	data(){
	  return{
	  	  tabIndex: 0,
	      tabList: [
			  { label: "第一" },
			  { label: "第二" },
			  { label: "第三" },
			  { label: "第四" },
			  { label: "第五" },
			  { label: "第六" },
			  { label: "第七" },
		  ],
	  }
	}
}

二、不可滑动的 tab

效果图二:
在这里插入图片描述
在这里插入图片描述

实现:
方法一:
组件代码:

<template>
  <view>
    <view class="tab-box">
      <view
        class="tab-item"
        @click="chooseTab(index)"
        :class="{ active: index === currentTab }"
        v-for="(item, index) in tabList"
        :key="index"
      >
        {{ item[labelKey] }}
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: "baseTab",
  props: {
    tabList: {
      type: Array,
      default: () => [],
    },
    labelKey: {
      type: String,
      default: "label",
    },
    tabIndex: {
      type: [Number, String],
      default: 0,
    },
  },
  data() {
    return {
      currentTab: this.tabIndex,
    };
  },
  methods: {
    chooseTab(index) {
      this.currentTab = index;
      this.$emit("chooseTab", index);
    },
  },
};
</script>

<style lang="less" scoped>
.tab-box {
  display: flex;
  align-items: center;
  margin-bottom: 30rpx;
  border-bottom: 1rpx solid #eee;
  .tab-item {
    flex: 1;
    position: relative;
    top: 4rpx;
    line-height: 37rpx;
    padding: 0 0 15rpx;
    text-align: center;
  }
  .active {
    color: #0f5eee;
    font-weight: bold;
    border-bottom: 6rpx solid #0f5eee;
  }
}
</style>

方法二:
每个tab是否平分自动计算宽度

组件代码:

<template>
  <view class="tab-con">
    <view class="tab-wrapper">
      <view
        v-for="(item, index) in tabList"
        :key="index"
        class="tab-item"
        style="width: 800rpx"
        @click="changeTab(index)"
        :class="{ 'tab-item-active': index === tabIndex }"
      >
        <text>{{ item[labelKey] }} </text>
        <view class="active-line"></view>
      </view>
    </view>
    <view class="tab-wrapper-bottom"></view>
  </view>
</template>

<script>
export default {
  name: "baseTab",
  props: {
    tabIndex: {
      type: [String, Number],
      default: 0,
    },
    tabList: {
      type: Array,
      default: () => [],
    },
    labelKey: {
      type: String,
      default: "label",
    },
  },
  data() {
    return {};
  },
  computed: {
    widthPercent() {
      const point = 1 / this.tabList.length;
      const formated = Number(point * 100).toFixed(2);
      return `${formated}%`;
    },
  },
  methods: {
    changeTab(index) {
      this.$emit("changeTab", index);
    },
  },
};
</script>

<style lang="less" scoped>
.tab-wrapper {
  height: 52rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tab-item {
  font-size: 28rpx;
  line-height: 38rpx;
  color: #bdbdbd;
  display: flex;
  align-items: center;
  position: relative;
  justify-content: center;
  font-family: Microsoft YaHei;
}

.tab-item-active {
  color: #333333;
  height: 52rpx;
  box-sizing: border-box;
}

.tab-item-active .active-line {
  height: 6rpx;
  width: 100rpx;
  background: #3ec3ae;
  border-radius: 2rpx;
  position: absolute;
  bottom: -12rpx;
}

.tab-wrapper-bottom {
  height: 2rpx;
  background: #e1e4e6;
  margin-top: 8rpx;
}
</style>

页面引用:

<base-tab :tabIndex="tabIndex" :tabList="tabList" @changeTab="changeTab"></base-tab>
data(){
	tabIndex: 0,  
    tabList: [
      { label: "第一" },
      { label: "第二" },
      { label: "第三" },  
    ],
}
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
uni-app中,可以通过自定义底部tabbar组件来实现切换动画效果。首先,在tab-bar组件中,可以使用unitabbar组件来实现底部tab切换功能。在tab-bar组件中,可以通过设置backgroundColor属性,color属性和tintColor属性来自定义底部tabbar的背景颜色,字体颜色和选中状态的图标高亮颜色。接着,在methods中的tabClick方法中,可以使用uni的redirectTo方法来进行tab页的跳转,并将当前tab的高亮索引更新为点击的tab的索引。这样,当点击底部tab时,页面会实现切换动画效果并跳转到对应的tab页。同时,可以根据自己的需求添加一些额外的功能,如实现tab的数字角标和tab页面的跳转。例如,在基础上可以添加tab的数字角标和tab页面跳转功能。为了保证底部tabbar的高度一致,可以在全局的数据中设置一个tabbarHeight属性,并在tab-bar组件中引用该属性。这样,就可以实现自定义底部tabbar切换动画效果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [H5版基于uni-app实现自定义底部tabbar效果(支持底部图标选中时的渐变效果)](https://blog.csdn.net/CherryLee_1210/article/details/106281571)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [uni-app 自定义底部导航栏的实现](https://blog.csdn.net/weixin_32786041/article/details/111911595)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Windyluna

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值