图书馆小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

198 lines
4.3 KiB

<template>
<view class="tab-container">
<view class="tab-box">
<scroll-view
id="_scroll"
scroll-x
class="scroll-view"
scroll-with-animation
:scroll-left="scrollLeft"
>
<view class="scroll-content">
<view class="tab-item-box">
<block v-for="(item, index) in tabList" :key="index">
<view
class="tab-item"
:id="'_tab_' + index"
:class="{ 'tab-item-active': activeIndex === index }"
@click="tabClick(index)"
:style="{
color: activeIndex === index ? defaultConfig.activeTextColor : defaultConfig.textColor
}"
>{{ item.label || item }}</view>
</block>
</view>
<!-- 滑块 -->
<view
class="underLine"
:style="{
transform: 'translateX(' + slider.left + 'px)',
width: defaultConfig.underLineWidth + 'px',
height: defaultConfig.underLineHeight + 'px',
backgroundColor: defaultConfig.underLineColor
}"
/>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
name: 'my-tabs',
props: {
tabData: {
type: Array,
default: () => []
},
defaultIndex: {
type: Number,
default: 0
},
config: {
type: Object,
default: () => ({})
}
},
data() {
return {
tabList: [],
activeIndex: 0,
slider: { left: 0 },
scrollLeft: 0,
defaultConfig: {
textColor: '#333333',
activeTextColor: '#01a4fe',
underLineWidth: 24,
underLineHeight: 2,
underLineColor: '#01a4fe'
}
}
},
watch: {
tabData: {
handler(val) {
this.tabList = val
this.$nextTick(() => {
this.updateTabWidth()
})
},
immediate: true
},
defaultIndex: {
handler(val) {
if (this.tabList.length === 0) return
this.activeIndex = val
this.$nextTick(() => {
this.updateTabWidth()
})
},
immediate: true
},
config: {
handler(val) {
this.defaultConfig = { ...this.defaultConfig, ...val }
},
immediate: true
}
},
methods: {
updateTabWidth() {
if (this.tabList.length === 0) return
const query = uni.createSelectorQuery().in(this)
let finishCount = 0
this.tabList.forEach((item, index) => {
query.select(`#_tab_${index}`).boundingClientRect((res) => {
if (!res) return
item._slider = {
left: res.left + (res.width - this.defaultConfig.underLineWidth) / 2
}
finishCount++
if (finishCount === this.tabList.length) {
this.tabToIndex()
}
}).exec()
})
},
tabClick(index) {
this.activeIndex = index
this.tabToIndex()
this.$emit('tabClick', index)
},
tabToIndex() {
if (!this.tabList.length || !this.tabList[this.activeIndex]?._slider) {
return
}
this.slider.left = this.tabList[this.activeIndex]._slider.left
}
}
}
</script>
<style lang="scss" scoped>
.tab-container {
font-size: 14px;
height: 45px;
line-height: 45px;
.tab-box {
width: 100%;
height: 45px;
display: flex;
position: relative;
.scroll-view {
white-space: nowrap;
width: 100%;
height: 100%;
box-sizing: border-box;
.scroll-content {
width: 100%;
height: 100%;
position: relative;
.tab-item-box {
display: flex;
justify-content: space-around;
height: 100%;
.tab-item {
height: 100%;
display: inline-block;
text-align: center;
padding: 0 20px;
position: relative;
color: #333;
&-active {
color: #01a4fe;
}
}
}
.underLine {
height: 2px;
width: 25px;
background-color: #01a4fe;
border-radius: 3px;
transition: 0.3s;
position: absolute;
bottom: 0;
}
}
}
}
/* #ifdef H5 */
::v-deep .uni-scroll-view::-webkit-scrollbar {
display: none;
}
/* #endif */
}
</style>