tabControl-tag.vue

<template name="tabControl">
		<scroll-view  scroll-x="true" :style="'background-color:'+bgc+';top:'+top+'px;'" :class="fixed?'fxied':''" :scroll-left='scrollLeft' scroll-with-animation id="tabcard">
			<view class="tabList" :style="isEqually?'display: flex;justify-content: space-between;padding-left:0;':''">
				<view
					:class="'tabItem'+(currentIndex==index?' thisOpenSelect':'')"
					:style="isEqually? 'width:'+windowWidth/values.length+'px;margin-right:0;':''"
					v-for="(item,index) in values" 
					:id="'item'+index"
					:key='index' 
					@click="_onClick(index)">
					<text :style="(currentIndex==index?'font-size:'+activeSize+'rpx;color:'+activeColor:'font-size:'+itemSize+'rpx')">{{item}}</text>
					<view class="activeLine" :style="{width: lineWidth+'rpx'}"></view>
				</view>
			</view>
		</scroll-view>
</template>

<script>
	export default {
		name:'tabControl',
		props:{
			current: {
				type: Number,
				default: 0
			},
			values: {
				type: Array,
				default () {
					return []
				}
			},
			bgc:{
				type:String,
				default:''
			},
			fixed:{
				type:Boolean,
				default:false
			},
			scrollFlag:{
				type:Boolean,
				default:false
			},
			lineWidth:{
				type:Number,
				default: 100
			},
			itemSize:{
				type:Number,
				default: 30
			},
			activeSize:{
				type:Number,
				default: 32
			},
			activeColor:{
				type:String,
				default:''
			},
			top:{
				type:Number,
				default: 0
			},
			isEqually:{
				type:Boolean,
				default:false
			}
		},
		data() {
			return {
				currentIndex: 0,
				windowWidth:0,	//设备宽度
				leftList:[],	//选项距离左边的距离
				widthList:[],	//选项宽度
				scrollLeft:0,   //移动距离
				newScroll:0,    //上一次移动距离(用来判断是左滑还是右滑)
				wornScroll:0,    //上一次移动距离(用来判断是左滑还是右滑)
			};
		},
		created(){
			
		},
		mounted(){
			setTimeout(()=>{
				uni.createSelectorQuery().in(this).select("#tabcard").boundingClientRect((res)=>{
					this.$emit('getTabCardHeight', {height:res.height})
				}).exec()
				uni.getSystemInfo({
				    success: (res)=> {
						this.windowWidth = res.windowWidth;
				        // console.log(this.windowWidth);
						this.values.forEach((i,v)=>{
							let info = uni.createSelectorQuery().in(this);
							info.select("#item"+v).boundingClientRect((res)=>{
								// 获取第一个元素到左边的距离
								// if(v==0){
								// 	this.startLenght = res.left
								// }
							    this.widthList.push(res.width)
								this.leftList.push(res.left)
								
							}).exec()
							
						})
						// console.log(this.leftList)
						// console.log(this.widthList)
				    }
				});
			})
		},
		created() {
			this.currentIndex = this.current
			if(this.scrollFlag){
				setTimeout(()=>{
					this.tabListScroll(this.current)
				},300)
			}
		},
		watch: {
			current(val) {
				if (val !== this.currentIndex) {
					this.currentIndex = val
					if(this.scrollFlag){
						this.tabListScroll(val)
					}
				}
			},
			
		},
		methods: {
			_onClick(index) {
				if (this.currentIndex !== index) {
					this.currentIndex = index
					this.$emit('clickItem', {currentIndex:index})
					// 开启滚动
					if(this.scrollFlag){
						this.tabListScroll(index)
					}
				}
			},
			// 选项移动
			tabListScroll(index){
				let scoll = 0;
				this.wornScroll = index;
				// this.wornScroll-this.newScroll>0 在向左滑  ←←←←←
				if(this.wornScroll-this.newScroll>0){
					for(let i = 0;i<this.leftList.length;i++){
						if(i>1&&i==this.currentIndex){
							scoll = this.leftList[i-1]
						}
					}
					// console.log('在向左滑',scoll)
				}else{
					if(index>1){
						for(let i = 0;i<this.leftList.length;i++){
							if(i<index-1){
								scoll = this.leftList[i]
							}
						}
					}else{
						scoll = 0
					}
					// console.log('在向右滑')
				}
				this.newScroll = this.wornScroll;
				this.scrollLeft = scoll;
			}
		}
	}
</script>

<style lang="less" scoped>
	.fxied{
		position: fixed;
		z-index: 2;
	}
	.tabList{
		padding-top: 24rpx;
		padding-left: 24rpx;
		padding-bottom: 8rpx;
		white-space: nowrap;
		text-align: center;
		.tabItem{
			margin-right: 60rpx;
			display: inline-block;
			position: relative;
			text{
				// font-size: 30rpx;
				line-height: 44rpx;
				color: #666;
				transition: all 0.3s ease 0s;
			}
			.activeLine{
				// width: 48rpx;
				height: 8rpx;
				border-radius: 4rpx;
				background-color: #F57341;
				margin-top: 8rpx;
				margin-left: 50%;
				transform: translateX(-50%);
				opacity: 0;
				transition: all 0.3s ease 0s;
			}
		}
		.tabItem:first-child{
			// margin-left: 22rpx;
		}
		.tabItem:last-child{
			margin-right: 24rpx;
		}
		.thisOpenSelect{
			text{
				color: #333;
				font-weight:600;
				// font-size: 32rpx;
			}
			.activeLine{
				opacity: 1;
			}
		}
	}
	
</style>

页面引用

<template>
	<view class="page">
		<tabControl :current="current" :values="items" bgc="#fff" :fixed="true" :scrollFlag="true" :isEqually="false" @clickItem="onClickItem"></tabControl>
		<!-- 使用 swiper 配合 滑动切换 -->
		<swiper class="swiper" style="height: 100%;" @change="scollSwiper" :current="current">
			<swiper-item v-for="(item, index) in items" :key="index">
				<!-- 使用 scroll-view 来滚动内容区域 -->
				<scroll-view scroll-y="true" style="height: 100%;">{{ item }}</scroll-view>
			</swiper-item>
		</swiper>
	</view>
</template>

<script>
import tabControl from '@/components/tabControl-tag/tabControl-tag.vue';
export default {
	components: { tabControl },
	data() {
		return {
			items: ['业绩统计', '选项卡2', '选项卡3', '选项卡4', '选项卡5'],
			current: 0
		};
	},
	onLoad() {},
	methods: {
		onClickItem(val) {
			this.current = val.currentIndex;
		},
		scollSwiper(e) {
			this.current = e.target.current;
		}
	}
};
</script>

<style>
page {
	height: 100%;
}
.page {
	padding-top: 98rpx;
	height: 100%;
}
</style>

1.使用方式:
scrollFlag --是否开启选项滚动(true -开启 false -关闭) 根据自己需求如果选项长度超出屏幕长度 建议开启
fixed --固定定位
bgc --背景色
values --选项数组
current --当前选中选项索引
isEqually --是否开启选项平分宽度(true,false)
lineWidth --下划线长度(在非平分选项状态下 可能会影响选项盒子的宽度-自行调试想要的效果,默认为48rpx)
itemSize --未选中选项字体大小(默认为30rpx)
activeSize --选中选项字体大小(默认为32rpx)
activeColor --选中选项字体颜色(默认#333)
top --选项卡固定定位 自定义top距离

注意:
使用fixed固定头部的时候 要将页面整体padding-top:98rpx;不然会盖住内容区域。
使用swiper实现滑动切换时 要将page 高度设置100% swiper高度100% 才可以全屏滑动切换

Logo

前往低代码交流专区

更多推荐