lgd-tab.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <template>
  2. <view>
  3. <view class="tabview">
  4. <scroll-view class="scrollView" scroll-x show-scrollbar="false" :scroll-left="scrollLeft"
  5. scroll-with-animation style="height: 74rpx;">
  6. <view class="tabBox" :style="{ 'justify-content': isOutWindow ? '' : 'space-around'}">
  7. <view class="items" v-for="(item, index) in tabValue" :key="index" @click="updateTab(index)">
  8. <view class="tabText" :class="index == tIndex ? 'active' : ''"
  9. :style="{ 'font-size': fontSize + 'px', color: index == tIndex ? textColor : ''}">
  10. {{item}}
  11. </view>
  12. </view>
  13. </view>
  14. <view class="underscore"
  15. :style="{ width: inderWidth + 'px', 'margin-left': indexLeft + boxLeft + 'px', 'background-color': underlineColor }" />
  16. </scroll-view>
  17. </view>
  18. <view class="gap" style="height: 74rpx;" :style="{'background-color': background }" />
  19. </view>
  20. </template>
  21. <script>
  22. export default {
  23. props: {
  24. value: {
  25. type: Number,
  26. },
  27. modelValue: {
  28. type: Number
  29. },
  30. tabValue: { // tab数据
  31. type: Array,
  32. default: [],
  33. required: true
  34. },
  35. textColor: { // 颜色
  36. type: String,
  37. default: '#333'
  38. },
  39. underlineColor: {
  40. type: String,
  41. default: '#34b2fa'
  42. },
  43. fontSize: { // 字体大小
  44. type: Number,
  45. default: 16
  46. },
  47. background: {
  48. type: String,
  49. default: '#fff'
  50. }
  51. },
  52. data() {
  53. return {
  54. windowsWidth: 0, // 设备窗口大小
  55. boxLeft: 0,
  56. isOutWindow: false, // tab是否超出屏幕
  57. inderWidth: 0, // 下划线宽度
  58. indexLeft: 0, // 下划线距左边距离
  59. scrollLeft: 0,
  60. tIndex: 0, // tab下标
  61. };
  62. },
  63. watch: {
  64. // 监听TAB内容更改
  65. tabValue: {
  66. handler(newValue, oldValue) {
  67. this.$nextTick(() => {
  68. this.clickTab(this.value || this.modelValue || 0)
  69. })
  70. },
  71. deep: true
  72. },
  73. modelValue(val) {
  74. this.clickTab(val)
  75. },
  76. value(val) {
  77. this.clickTab(val)
  78. },
  79. },
  80. methods: {
  81. /// 初始化
  82. init() {
  83. let that = this;
  84. // 判断tab是否超出屏幕
  85. uni.createSelectorQuery().in(this).selectAll(".items").boundingClientRect().exec((data) => {
  86. if (data[0][that.tabValue.length - 1].right > that.windowsWidth) {
  87. that.isOutWindow = true
  88. }
  89. that.$nextTick(() => {
  90. that.clickTab(that.value || that.modelValue || 0)
  91. })
  92. })
  93. },
  94. updateTab(index) {
  95. // #ifndef VUE3
  96. this.$emit('input', index)
  97. // #endif
  98. // #ifdef VUE3
  99. this.$emit('update:modelValue', index)
  100. // #endif
  101. },
  102. /// 点击TAB
  103. clickTab(index) {
  104. // 更改选中下标
  105. this.tIndex = index
  106. this.$emit("change", index)
  107. // 获取盒子移动距离
  108. if (this.isOutWindow && index >= 0) {
  109. uni.createSelectorQuery().in(this).select(".tabBox").boundingClientRect().exec((data) => {
  110. if (index == 0) {
  111. this.boxLeft = 0
  112. } else {
  113. // 移动距离
  114. this.boxLeft = -data[0].left
  115. }
  116. })
  117. }
  118. uni.createSelectorQuery().in(this).selectAll(".items").boundingClientRect().exec((data) => {
  119. let width = data[0][index].width
  120. let left = data[0][index].left
  121. let newLeft = 0
  122. // tab超出屏幕
  123. if (this.isOutWindow) {
  124. if (index == 0) {
  125. left = 0
  126. }
  127. // 防止移动后距离缩短问题
  128. for (let i = 0; i < index; i++) {
  129. newLeft += data[0][i].width
  130. }
  131. // 是否需要居中
  132. if (this.windowsWidth / 2 < newLeft + width) {
  133. this.scrollLeft = width / 2 - (this.windowsWidth / 2 - newLeft)
  134. } else {
  135. this.scrollLeft = 0
  136. }
  137. }
  138. // 点击tab宽度
  139. this.inderWidth = width / 2
  140. // 移动距离
  141. this.indexLeft = (width - width / 2) / 2 + left
  142. })
  143. },
  144. },
  145. mounted() {
  146. // 获取屏幕宽度
  147. this.windowsWidth = uni.getSystemInfoSync().windowWidth
  148. // 初始化
  149. this.init()
  150. }
  151. }
  152. </script>
  153. <style>
  154. .tabview {
  155. width: 100vw;
  156. position: absolute;
  157. left: 0;
  158. }
  159. .scrollView {
  160. width: 100%;
  161. white-space: nowrap;
  162. }
  163. .tabBox {
  164. display: flex;
  165. align-items: center;
  166. }
  167. .items {
  168. line-height: 60rpx;
  169. padding: 0 20rpx;
  170. }
  171. .tabText {
  172. color: #666666;
  173. }
  174. .active {
  175. font-weight: bold;
  176. }
  177. .underscore {
  178. height: 3px;
  179. transition: .2s all;
  180. border-radius: 6rpx;
  181. }
  182. /deep/.uni-scroll-view::-webkit-scrollbar {
  183. display: none
  184. }
  185. </style>