uniApp 封装一个常用的tabs组件

<template>
	<view class="tabs-box">
		<view class="tabs-main" :style="{paddingBottom:comPaddingBottom}">
			<view @click="changeIndex(index)" class="content-item" v-for="(item,index) in dataList" :key="index">
				<view class="top-text">
					<text :class="{'_font-bold':currIndex==index}">{{item.name}}</text>
					<image v-show="currIndex==index" class="icon-image" src="/static/global_image/active_icon.png">
					</image>
				</view>
			</view>
			<view class="active" :style="{'left':comLeft,'width':comWidth,height:comHeight}"></view>
		</view>
	</view>
</template>

<!-- @该组件传入一个事件用于改变tabs下标 @changeIndex-->
<!-- @传入一个data数组对象 必须为 value name 的键值对 -->
<script>
	export default {
		data() {
			return {
				itemWidth: '', //每个tabs-item 元素的宽

			}
		},
		props: {
			dataList: Array, //组件要求传入一个和data 格式相同的列表 用于展示数据
			currIndex: Number, //组件需要一个index值来控制tabs 下标
			LineOffset:0,//下方线条与上方item的距离 单位rpx
			LineHeight: {
				type: Number,
				default: 6
			}, //下方滑块line高度 默认6rpx高度
			lineWidth: {
				type: Number,
				default: 1
			}, //下方滑块的宽度 默认为每个item的宽度 请传入百分比值 例如 1 = 100% 
		},
		mounted() {
			this.getWidth(); //获取组件宽度
		},
		computed: {
			comPaddingBottom(){
				return this.LineOffset+'rpx'
			},
			comHeight() {
				return this.LineHeight + 'rpx'
			},
			comWidth() {
				let width = this.itemWidth.width * this
				.lineWidth; //组件支持传入相对于每个item 来计算的  滑块的宽  例如 每个item宽度100 *0.8 意味着line将是80
				return width + 'px'
			},
			comLeft() {
				// 规定左偏移数值 10 px
				let py = 0;
				//获取当前坐标 curr
				py = (this.itemWidth.width - this.itemWidth.width * this.lineWidth) / 2;
				let index = this.currIndex;
				// 最终移动位置 =(index * 93.75 )+ py 
				let numSum = (index * this.itemWidth.right) + py;
				//左移   
				return numSum + 'px'
			}
		},
		methods: {
			changeIndex( index) {
				//告知父组件当前选中项 并回传item
				this.$emit('changeIndex',  index);
			},
			getWidth() {
				this.$nextTick(async () => {
					//使用uni带的方法获取 元素的 宽度 为了适配各机型 
					let that = this;
					that.itemWidth = await that.$uGetRect('.' + 'content-item');
					console.log(that.itemWidth.right, '获取每个元素的宽度');
				})
			},
		}
	}
</script>

<style lang="scss">
	.tabs-box {
		.tabs-main {
			display: flex;
			justify-content: space-between;
			background-color: #FFF;
			padding: 10rpx 0;
			transition: left 2s;
			position: relative;

			.content-item {
				width: 100%;
				display: flex;
				flex-direction: column;
				align-items: center;
				border-right: 1rpx solid #EEEEEE;

				.top-text {
					position: relative;
					font-size: 30rpx;
					font-weight: 500;
					color: #666666;

					.icon-image {
						position: absolute;
						width: 28rpx;
						height: 28rpx;
						right: -10rpx;
						top: 0;
					}
				}

				.bottom-card {
					padding: 8rpx 40rpx;
					margin-top: 10rpx;
					border-radius: 20rpx;
					text-align: center;
					font-size: 24rpx;
					font-weight: 400;
					color: #666666;
					position: relative;
					z-index: 10;
				}
			}
		}

		.active {
			position: absolute;
			background: #FFDD00;
			color: #333333;
			transition: all .5s;
			bottom: 0rpx;
			padding: 4rpx 20rpx;
			border-radius: 20rpx;
			z-index: 1;
		}
	}
</style>

组件会自动计算好一些参数 ,带动画的 效果如图  

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值