页面代码:
<template>
<view>
<me-tabs :tabs="tabs" v-model="tabIndex" :fixed="true" :tabWidth="130"></me-tabs>
</view>
</template>
<script>
import MeTabs from "@/components/me-tabs.vue"
export default {
data() {
return {
tabs:[{
name:"全部"},{
name:"等付款"},{
name:"待发货"},{
name:"全部"},{
name:"等付款"},{
name:"待发货"},{
name:"全部"},{
name:"等付款"},{
name:"待发货"},{
name:"全部"},{
name:"等付款"},{
name:"待发货"},{
name:"待收货"},{
name:"已收货"},{
name:"全部1"},{
name:"等付款1"},{
name:"待发货1"},{
name:"待收货1"},{
name:"已收货1"},],
tabIndex:0
}
},
methods: {
},
components:{
MeTabs
}
}
</script>
<style>
</style>
组件代码:
<!-- tab组件: <me-tabs v-model="tabIndex" :tabs="tabs" @change="tabChange"></me-tabs> -->
<template>
<view class="me-tabs" :class="{'tabs-fixed': fixed}" :style="{height: tabHeightVal}">
<scroll-view v-if="tabs.length" :id="viewId" :scroll-left="scrollLeft" scroll-x scroll-with-animation :scroll-animation-duration="300">
<view class="tabs-item" :class="{'tabs-flex':!isScroll, 'tabs-scroll':isScroll}">
<!-- tab -->
<view class="tab-item" :style="{width: tabWidthVal, height: tabHeightVal, 'line-height':tabHeightVal}" v-for="(tab, i) in tabs" :class="{'active': value===i}" :key="i" @click="tabClick(i)">
{
{
getTabName(tab)}}
</view>
<!-- 下划线 -->
<view class="tabs-line" :style="{left:lineLeft}"></view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
props:{
tabs: {
type: Array,
default(){
return []
}
},
nameKey: {
type: String,
default: 'name'
},
value: {
type: [String, Number],
default: 0
},
fixed: Boolean,
tabWidth: Number,
height: {
type: Number,
default: 64
}
},
data() {
return {
viewId: 'id_' + Math.random().toString(36).substr(2,16),
scrollLeft: 0
}
},
computed: {
isScroll(){
return this.tabWidth && this.tabs.length
},
tabHeightPx(){
return uni.upx2px(this.height)
},
tabHeightVal(){
return this.tabHeightPx+'px'
},
tabWidthPx(){
return uni.upx2px(this.tabWidth)
},
tabWidthVal(){
return this.isScroll ? this.tabWidthPx+'px' : ''
},
lineLeft() {
if (this.isScroll) {
return this.tabWidthPx * this.value + this.tabWidthPx/2 + 'px'
} else{
return 100/this.tabs.length*(this.value + 1) - 100/(this.tabs.length*2) + '%'
}
}
},
watch: {
tabs() {
this.warpWidth = null;
this.scrollCenter();
},
value() {
this.scrollCenter();
}
},
methods: {
getTabName(tab){
return typeof tab === "object" ? tab[this.nameKey] : tab
},
tabClick(i){
if(this.value!=i){
this.$emit("input",i);
this.$emit("change",i);
}
},
async scrollCenter(){
if(!this.isScroll) return;
if(!this.warpWidth){
let rect = await this.initWarpRect()
this.warpWidth = rect ? rect.width : uni.getSystemInfoSync().windowWidth;
}
let tabLeft = this.tabWidthPx * this.value + this.tabWidthPx/2;
let diff = tabLeft - this.warpWidth/2
this.scrollLeft = diff;
this.scrollTimer && clearTimeout(this.scrollTimer)
this.scrollTimer = setTimeout(()=>{
this.scrollLeft = Math.ceil(diff)
},400)
},
initWarpRect(){
return new Promise(resolve=>{
setTimeout(()=>{
let query = uni.createSelectorQuery();
query = query.in(this)
query.select('#'+this.viewId).boundingClientRect(data => {
resolve(data)
}).exec();
},20)
})
}
},
mounted() {
this.scrollCenter()
}
}
</script>
<style lang="scss">
.me-tabs{
position: relative;
font-size: 24rpx;
background-color: #fff;
border-bottom: 1rpx solid #eee;
box-sizing: border-box;
overflow-y: hidden;
background-color: #fff;
&.tabs-fixed{
z-index: 990;
position: fixed;
top: var(--window-top);
left: 0;
width: 100%;
}
.tabs-item{
position: relative;
white-space: nowrap;
padding-bottom: 30rpx;
box-sizing: border-box;
.tab-item{
position: relative;
text-align: center;
box-sizing: border-box;
&.active{
font-weight: bold;
color: red;
}
}
}
.tabs-flex{
display: flex;
.tab-item{
flex: 1;
}
}
.tabs-scroll{
.tab-item{
display: inline-block;
}
}
.tabs-line{
z-index: 1;
position: absolute;
bottom: 30rpx;
width: 50rpx;
height: 6rpx;
transform: translateX(-50%);
border-radius: 4rpx;
transition: left .3s;
background: red;
}
}
</style>