<template> <view class="_tab-box" :style="{fontSize: defaultConfig.fontSize + 'rpx', color: defaultConfig.color}"> <scroll-view id="_scroll" :scroll-x="true" class="scroll-view-h" scroll-with-animation :scroll-left="slider.scrollLeft"> <view class="_scroll-content"> <view class="_tab-item-box" :class="[defaultConfig.itemWidth ? '_clamp' : '_flex']"> <block v-for="(item, index) in tabList" :key="index" > <view class="_item" :id="'_tab_'+index" :class="{ '_active': tagIndex === index }" :style="{color: tagIndex == index ? defaultConfig.activeColor : defaultConfig.color, 'width': defaultConfig.itemWidth ? defaultConfig.itemWidth + 'rpx' : ''}" @click="tabClick(index)">{{ item[defaultConfig.key] || item }}</view> </block> </view> <view class="_underline" :style="{ transform: 'translateX(' + slider.left + 'px)', width: slider.width + 'px', height: defaultConfig.underLineHeight + 'rpx', backgroundColor: defaultConfig.underLineColor, }" /> </view> </scroll-view> </view> </template> <script> export default { name: 'liuyuno-tabs', props: { list: { type: Array, default: () => ['全部', '测试', '测试宽度', '测试宽度三号', '测试宽度四号小星星', '测试宽度五号'] }, // 选中索引 activeIndex: { type: Number, default: 0 }, config: { type: Object, default:() => { return { color: '#999999',//默认时字体颜色 activeColor: '#000000',//选中时字体颜色 underLineColor: '#000000',//下滑线颜色 } } }, }, data() { return { tabList: [], tagIndex: 0, slider: { left: 0, width: 0, scrollLeft: 0 }, scorll: {}, defaultConfig: { // 要显示的key key: 'name', // 字体大小 rpx fontSize: 26, // 字体颜色 color: '#313131', // 激活字体颜色 activeColor: '#e54d42', // item宽度 0为自动 itemWidth: 0, // 下划线左右边距,文字宽度加边距 rpx underLinePadding: 10, // 下划线宽度 rpx 注意:设置了此值 underLinePadding 失效 underLineWidth: 0, // 下划线高度 rpx underLineHeight: 4, // 下划线颜色 underLineColor: '#e54d42', }, }; }, watch: { list(value) { this.updateData(); setTimeout(() => { this.updateTabWidth(); }, 0); }, config(value) { this.updateConfig(); }, activeIndex(value) { this.tagIndex = this.activeIndex; this.tabToIndex(this.tagIndex); } }, mounted() { this.updateConfig(); this.tagIndex = this.activeIndex; this.updateData(); this.$nextTick(() => { this.calcScrollPosition(); }) }, methods: { updateData() { let data = []; if (typeof(this.list[0])=='string') { this.list.forEach((item, index) => { data.push({ name: item, }) }); this.defaultConfig.key = 'name'; } else { data = JSON.parse(JSON.stringify(this.list)); } this.tabList = data; }, updateConfig() { this.defaultConfig = Object.assign(this.defaultConfig, this.config); }, calcScrollPosition() { const query = uni.createSelectorQuery().in(this); query.select('#_scroll').boundingClientRect((res) => { this.scorll = res; this.updateTabWidth(); }).exec(); }, updateTabWidth(index = 0) { let data = this.tabList; if (data.length == 0) return false; const query = uni.createSelectorQuery().in(this); query.select('#_tab_' + index).boundingClientRect((res) => { data[index]._slider = { width: res.width, left: res.left, scrollLeft: res.left - (data[index - 1] ? data[index - 1]._slider.width : 0), }; if (this.tagIndex == index) { this.tabToIndex(this.tagIndex); } index++; if (data.length > index) { this.updateTabWidth(index); } }).exec(); }, tabToIndex(index) { let _slider = this.tabList[index]._slider; let width = uni.upx2px(this.defaultConfig.underLineWidth); if (!width) { if (this.defaultConfig.itemWidth) { width = uni.upx2px(this.defaultConfig.itemWidth); } else { width = this.tabList[index][this.defaultConfig.key].length * uni.upx2px(this.defaultConfig.fontSize); } width += uni.upx2px(this.defaultConfig.underLinePadding) * 2; } let scorll_left = this.scorll.left || 0; this.slider = { left: _slider.left - scorll_left + (_slider.width - width) / 2, width: width, scrollLeft: _slider.scrollLeft - scorll_left, } }, tabClick(index) { this.tagIndex = index; this.tabToIndex(index); this.$emit('changeEv', index); } } } </script> <style lang="scss" scoped> ._tab-box { width: 100%; display: flex; font-size: 26rpx; position: relative; height: 90rpx; line-height: 90rpx; z-index: 10; .scroll-view-h{ white-space:nowrap; width: 100%; height: 100%; box-sizing: border-box; ._scroll-content { width: 100%; height: 100%; position:relative; ._tab-item-box { height: 100%; &._flex { display: flex; ._item { flex: 1; } } &._clamp { ._item { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } } ._item { height: 100%; display: inline-block; text-align: center; padding: 0 30rpx; position: relative; text-align: center; color: #333; &._active { color: #e54d42; } } } ._underline { height: 4rpx; background-color: #e54d42; border-radius: 6rpx; transition: .5s; position: absolute; bottom: 0; } } } } .uni-scroll-view::-webkit-scrollbar { // 隐藏滚动条,但依旧具备可以滚动的功能 display: none } </style>