当前位置:   article > 正文

基于uniapp写的标签页_uniapp标签页

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="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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/280413
推荐阅读
相关标签