赞
踩
最近自己写了一个标签页的组件
<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>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。