jiuyiUniapp/jiuyi2/components/public/jy-shop-navigation/index.vue

180 lines
4.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="tab">
<scroll-view class="scroll" scroll-x scroll-with-animation :show-scrollbar="false" :scroll-left="scrollLeft">
<view class="list" :class="scroll ? '' : 'flex-row-left'" id="tab">
<view class="item fmid ptb10 plr20" :class="{'active': index === currentIndex}" :id="'tab-item-' + index"
v-for="(item, index) in list" :key="index" @click="clickTab(item, index)">
{{ item[titalName] }}
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
props: {
list: {
type: Array,
default: () => {
return []
}
},
titalName: {
type: String,
default: 'name'
},
// 是否滚动,默认是,否则是不滚动,按个数等分宽度
scroll: {
type: Boolean,
default: true
},
},
data() {
return {
scrollLeft: 0,
componentWidth: 0, // tabs组件宽度单位为px
parentLeft: 0, // 父元素(tabs组件)到屏幕左边的距离
scrollBarLeft: 0, // 移动bar需要通过translateX()移动的距离
tabItemRectInfo: [],
currentIndex: 0,
barFirstTimeMove: true
}
},
watch: {
list(n, o) {
// list变动时重制内部索引否则可能导致超出数组边界的情况
if (n.length !== o.length) this.currentIndex = 0;
this.$nextTick(() => {
this.init();
});
},
},
mounted() {
this.init()
},
methods: {
init() {
this.$nextTick(() => {
uni.createSelectorQuery().in(this).select(`#tab`).fields({
size: true,
rect: true
}, data => {
this.parentLeft = data.left;
// tabs组件的宽度
this.componentWidth = data.width;
}).exec();
this.getTabItemRect()
})
},
getTabItemRect() {
let query = uni.createSelectorQuery().in(this);
for (let i = 0; i < this.list.length; i++) {
// 只要size和rect两个参数
query.select(`#tab-item-${i}`).fields({
size: true,
rect: true
});
}
query.exec((data) => {
this.tabItemRectInfo = data
this.scrollByIndex()
})
},
scrollByIndex() {
let tabInfo = this.tabItemRectInfo[this.currentIndex]
if (!tabInfo) return
// 活动tab的宽度
let tabWidth = tabInfo.width
let offsetLeft = tabInfo.left - this.parentLeft
// 将活动的tabs-item移动到屏幕正中间实际上是对scroll-view的移动
let scrollLeft = offsetLeft - (this.componentWidth - tabWidth) / 2
this.scrollLeft = scrollLeft < 0 ? 0 : scrollLeft;
// 计算当前活跃item到组件左边的距离
let left = tabInfo.left + tabInfo.width / 2 - this.parentLeft
this.scrollBarLeft = left - this.barWidth / 2;
if (this.barFirstTimeMove == true) {
setTimeout(() => {
this.barFirstTimeMove = false;
}, 100)
}
},
clickTab(item, index) {
// 点击当前活动tab不触发事件
if (index === this.currentIndex) return
this.currentIndex = index
this.$emit('tabItemClick', item, index)
this.scrollByIndex()
}
}
}
</script>
<style lang="scss" scoped>
.tab {
position: sticky;
top: 88rpx;
left: 0;
width: 100%;
z-index: 9;
}
scroll-view {
box-sizing: border-box;
height: 100%;
}
::v-deep ::-webkit-scrollbar {
display: none
}
/* #ifndef APP-NVUE */
::-webkit-scrollbar,
::-webkit-scrollbar,
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
/* #endif */
/* #ifdef H5 */
// 通过样式穿透隐藏H5下scroll-view下的滚动条
scroll-view ::v-deep ::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
/* #endif */
.scroll {
position: relative;
white-space: nowrap;
width: 100%;
.list {
position: relative;
width: 100%;
white-space: nowrap;
}
.item {
position: relative;
display: inline-block;
color: #8C8C8C;
//
&.active {
color: #333;
font-weight: bold;
transform: scale(1.1);
}
}
}
</style>