基于uniapp写的标签页
最近自己写了一个标签页的组件<template><view class="fu-page" :style="{ position: sticky ? 'sticky' : 'initial', top: top + 'px', 'z-index': zIndex }"><scroll-view class="fu-tab" scroll-x :scroll-left=
·
最近自己写了一个标签页的组件
<template>
<view class="fu-page" :style="{ position: sticky ? 'sticky' : 'initial', top: top + 'px', 'z-index': zIndex }">
<scroll-view class="fu-tab" scroll-x :scroll-left="moveX" :scroll-with-animation="animation" :style="{ height: height + 'rpx', 'line-height': height + 'rpx' }">
<view :class="{'fu-flex':scrollspy}">
<view
class="fu-tab-item"
:class="[active == index ? 'active' : '', 'item-active-' + index]"
:style="{ color: active == index ? activeColor : inactiveColor, 'font-size': size + 'rpx' }"
v-for="(item, index) in tabs"
:key="index"
@click="tabChange($event, item[nodeKey], index)"
>
{{ item[nodeTitle] }}
</view>
<view
class="fu-tab-line"
:style="{ width: getWidth + 'rpx', left: left, height: lineHeight + 'rpx', background: lineColor, transition: animation, bottom: bottom + 'rpx' }"
></view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
props: {
//底部条线宽
'line-width': {
type: [Number, String],
default: 40
},
//底部条高度
'line-height': {
type: [Number, String],
default: 4
},
//底部调颜色
'line-color': {
type: String,
default: '#f02523'
},
//底部条位置
bottom: {
type: [Number, String],
default: 8
},
// tab高度
height: {
type: [Number, String],
default: 96
},
//字体大小
size: {
type: [Number, String],
default: 32
},
//选中状态
'active-color': {
type: String,
default: '#f02523'
},
// 默认状态
'inactive-color': {
type: String,
default: '#5f5f5f'
},
//数据
tabs: {
type: [Object, Array]
},
//动画
animation: {
type: String,
default: 'all .3s ease'
},
// 标签名称
'node-title': {
type: String,
default: 'name'
},
// 需要返回的唯一标识
'node-key': {
type: String,
default: 'id'
},
// 是否使用粘性布局
sticky: {
type: Boolean,
default: false
},
// 粘性布局离顶部高度
top: {
type: [String, Number],
default: 0
},
'z-index': {
type: [String, Number],
default: 99
},
// 是否开启flex
scrollspy:{
type: Boolean,
default: false
}
},
data() {
return {
active: 0,
left: '0rpx',
getWidth: 40,
lineWidthArray: [],
parentWidth: 0,
moveX: 0
};
},
computed: {},
watch: {
// 数据加载之后计算
tabs(newVal, oldVal) {
this.$nextTick(function(){
this.getSpacing();
})
}
},
mounted() {
// 隐藏显示之后触发
if(this.tabs.length>0){
this.$nextTick(function(){
this.getSpacing();
})
}
},
methods: {
tabChange(e, id, index) {
let _this = this;
let windowWidth = uni.getSystemInfoSync().windowWidth;
let activeItem = `item-active-${index}`;
this.active = index;
//事件源离左边距离
let offsetLeft = (e.target.offsetLeft * 750) / windowWidth;
//事件源宽度
let targetWidth = this.lineWidthArray[index];
// 底部显示条需要位移到的位置
this.$nextTick(function() {
let lineOffsetLeft = Math.ceil(offsetLeft + (targetWidth / 2 - this.getWidth / 2));
this.left = lineOffsetLeft + 'rpx';
});
// 获取父级宽度
let objParent = uni
.createSelectorQuery()
.in(this)
.select('.fu-tab');
let parentWidth;
objParent
.boundingClientRect(function(data) {
parentWidth = (data.width * 750) / windowWidth;
let moveX = Math.ceil(offsetLeft - (parentWidth - targetWidth) / 2);
// 转为px scoll-view接受的值为px
_this.moveX = (moveX * windowWidth) / 750;
})
.exec();
let data = {};
data.index = index;
data[this.nodeKey] = id;
this.$emit('change', data);
},
isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
},
getSpacing(){
let _this = this;
let {windowWidth,pixelRatio} = uni.getSystemInfoSync();
// console.log(uni.getSystemInfoSync())
// console.log(pixelRatio)
// 底部条宽度是否超过了标签最小宽度
let lineWidthArray = [];
let lwa = [];
if (this.isArray(this.tabs) && this.tabs.length > 0) {
this.$nextTick(function() {
// 主要计算底部线条宽度是否超出了最小的标签宽度 若超过线条宽度就显示为最小的标签宽度 start
this.tabs.forEach((val, i) => {
let activeItem = `item-active-${i}`;
let obj = uni
.createSelectorQuery()
.in(this)
.select(`.${activeItem}`);
obj
.boundingClientRect(function(data) {
lineWidthArray.push(Math.floor((data.width * 750) / windowWidth));
lwa.push(data.width)
})
.exec();
});
this.lineWidthArray = lineWidthArray;
this.parentWidth = lineWidthArray.reduce(function(total, curr) {
return total + curr;
}, 0);
if (_this.lineWidth > Math.min(...lineWidthArray)) {
_this.getWidth = Math.min(...lineWidthArray);
} else {
_this.getWidth = _this.lineWidth;
}
// end
//计算底部显示条初始位置
let activeItem = `item-active-${this.active}`;
let obj = uni
.createSelectorQuery()
.in(this)
.select(`.${activeItem}`);
obj
.boundingClientRect(function(data) {
console.log(data);
let targetWidth = Math.floor((data.width * 750) / windowWidth);
setTimeout(()=>{
_this.left = Math.floor((data.left)*750/windowWidth + targetWidth / 2 - _this.getWidth / 2) + 'rpx';
},200)
})
.exec();
});
}
}
}
};
</script>
<style scoped lang="scss">
.fu-page {
background: #ffffff;
border-bottom: 1rpx solid #f1f1f1;
}
.fu-tab {
height: 96rpx;
line-height: 96rpx;
// overflow-x: scroll;
// overflow-y: hidden;
font-size: 32rpx;
color: #5f5f5f;
white-space: nowrap;
// position: relative;
background: #ffffff;
transition: all 0.3s ease;
.fu-tab-item {
padding: 0 30rpx;
display: inline-block;
&.active {
color: #f02523;
}
}
.fu-tab-line {
position: absolute;
bottom: 4rpx;
left: 0;
width: 40rpx;
background: #f02523;
height: 4rpx;
border-radius: 2rpx;
transition: all 0.3s ease;
}
.fu-flex{
display: flex;
justify-content: space-around;
}
}
</style>
更多推荐
已为社区贡献1条内容
所有评论(0)