<template>
<view class="tabs-list">
<scroll-view
ref="scrollRef"
class="scroll-wrap"
scroll-x="true"
:scroll-left="scrollLeft"
>
<view
class="tabs-item"
v-for="(d,i) in list"
:key="i"
:class="{active: i === innerCurrent }"
@click="tansItemClick(d,i)"
>
<view class="tabs-item-box">
<view class="name">
{{ d.name }}
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
name:"m-tabs-scroll"
}
</script>
<script setup>
import { defineProps, ref, defineEmits, getCurrentInstance, watch, nextTick, onMounted} from 'vue';
const props = defineProps({
list: {
type: Array,
default: () => []
},
current: {
type: Number,
default: 0
}
})
const emits = defineEmits(['change', 'click']);
const instance = getCurrentInstance();
const innerCurrent = ref(0);
const tabsRect = ref({})
const tabRect = ref([]);
const scrollLeft = ref(0);
const scrollViewWidth = ref(0);
watch(() => props.list, () => {
nextTick(() => {
resize();
})
},{
immediate: true
}
)
watch(() => props.current, (newValue) => {
if (newValue !== innerCurrent.value) {
innerCurrent.value = newValue
nextTick(() => {
resize()
})
}
},{
immediate: true
}
)
function resize() {
if(props.list.length === 0) {
return
}
Promise.all([setTabsRect(), setTabRect()]).then(() => {
setScrollLeft()
})
}
function setTabRect() {
return new Promise(resolve => {
const query = uni.createSelectorQuery().in(instance.proxy);
query.selectAll('.tabs-item').boundingClientRect((rects) => {
scrollViewWidth.value = 0;
tabRect.value = rects.map(rect => {
scrollViewWidth.value += rect.width;
return rect
});
resolve();
}).exec();
})
}
function setTabsRect() {
return new Promise(resolve => {
const query = uni.createSelectorQuery().in(instance.proxy);
query.select('.scroll-wrap').boundingClientRect((rect) => {
tabsRect.value = rect;
resolve()
}).exec();
})
}
function tansItemClick(data, index) {
emits('click', {
index,
data
})
if(innerCurrent.value !== index) {
emits('change', {
index,
data
})
}
innerCurrent.value = index;
setScrollLeft()
}
function setScrollLeft() {
const offsetLeft = tabRect.value
.slice(0, innerCurrent.value)
.reduce((total, curr) => {
return total + curr.width;
}, 0)
const windowWidth = uni.getWindowInfo().windowWidth;
const tabsRectWidth = windowWidth - (tabsRect.value.left || 0) - (tabsRect.value.right || 0);
const item = tabRect.value[innerCurrent.value];
scrollLeft.value = item.left - tabsRectWidth / 2 + item.width / 2;
}
</script>
<style scoped lang="scss">
.tabs-list {
margin-top: 40rpx;
.scroll-wrap {
white-space: nowrap;
height: 120rpx;
}
.tabs-item {
display: inline-block;
min-width: 180rpx;
height: 76rpx;
padding: 0rpx 10rpx;
box-sizing: border-box;
&.active {
.tabs-item-box {
background-color: #418BFE;
color: #fff;
&::after {
content: ' ';
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -14rpx;
width: 14rpx;
height: 14rpx;
background-size: 100% 100%;
// background-image: url('~@/static/icon4.png');
}
}
}
.tabs-item-box {
background: #F8FCFE;
border-radius: 10rpx;
position: relative;
color: #323232;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
.name {
font-family: PingFang SC;
font-weight: 500;
font-size: 28rpx;
}
}
}
}
</style>