tui-tabs.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <template>
  2. <view class="tui-tabs-view" :class="[isFixed?'tui-tabs-fixed':'tui-tabs-relative',unlined?'tui-unlined':'']" :style="{height:height+'rpx',padding:`0 ${padding}rpx`,background:bgColor,top:isFixed?top+'px':'auto'}">
  3. <view v-for="(item,index) in tabs" :key="index" class="tui-tabs-item" :style="{width:itemWidth}" @tap.stop="swichTabs(index)">
  4. <view class="tui-tabs-title" :class="{'tui-tabs-active':currentTab==index,'tui-tabs-disabled':item.disabled}" :style="{color:currentTab==index?selectedColor:color,fontSize:size+'rpx',lineHeight:size+'rpx',fontWeight:bold && currentTab==index?'bold':'normal'}">{{item.name}}</view>
  5. </view>
  6. <view class="tui-tabs-slider" :style="{transform:'translateX('+scrollLeft+'px)',width:sliderWidth+'rpx',height:
  7. sliderHeight+'rpx',borderRadius:sliderRadius,bottom:bottom,background:sliderBgColor,marginBottom:bottom=='50%'?('-'+sliderHeight/2+'rpx'):0}"></view>
  8. </view>
  9. </template>
  10. <script>
  11. export default {
  12. name: "tuiTabs",
  13. props: {
  14. //标签页
  15. tabs: {
  16. type: Array,
  17. default () {
  18. return []
  19. }
  20. },
  21. //rpx
  22. height: {
  23. type: Number,
  24. default: 80
  25. },
  26. //rpx 只对左右padding起作用,上下为0
  27. padding: {
  28. type: Number,
  29. default: 30
  30. },
  31. //背景色
  32. bgColor: {
  33. type: String,
  34. default: "#FFFFFF"
  35. },
  36. //是否固定
  37. isFixed: {
  38. type: Boolean,
  39. default: false
  40. },
  41. //px
  42. top: {
  43. type: Number
  44. // #ifndef H5
  45. ,
  46. default: 0
  47. // #endif
  48. // #ifdef H5
  49. ,
  50. default: 44
  51. // #endif
  52. },
  53. //是否去掉底部线条
  54. unlined: {
  55. type: Boolean,
  56. default: false
  57. },
  58. //当前选项卡
  59. currentTab: {
  60. type: Number,
  61. default: 0
  62. },
  63. //滑块宽度
  64. sliderWidth: {
  65. type: Number,
  66. default: 68
  67. },
  68. //滑块高度
  69. sliderHeight: {
  70. type: Number,
  71. default: 6
  72. },
  73. //滑块背景颜色
  74. sliderBgColor: {
  75. type: String,
  76. default: "#5677fc"
  77. },
  78. sliderRadius:{
  79. type: String,
  80. default: "50rpx"
  81. },
  82. //滑块bottom
  83. bottom: {
  84. type: String,
  85. default: "0"
  86. },
  87. //标签页宽度
  88. itemWidth: {
  89. type: String,
  90. default: "25%"
  91. },
  92. //字体颜色
  93. color: {
  94. type: String,
  95. default: "#666"
  96. },
  97. //选中后字体颜色
  98. selectedColor: {
  99. type: String,
  100. default: "#5677fc"
  101. },
  102. //字体大小
  103. size: {
  104. type: Number,
  105. default: 28
  106. },
  107. //选中后 是否加粗 ,未选中则无效
  108. bold: {
  109. type: Boolean,
  110. default: false
  111. }
  112. },
  113. watch: {
  114. currentTab() {
  115. this.checkCor();
  116. }
  117. },
  118. created() {
  119. setTimeout(() => {
  120. // 高度自适应
  121. uni.getSystemInfo({
  122. success: (res) => {
  123. this.winWidth = res.windowWidth;
  124. this.checkCor()
  125. }
  126. });
  127. }, 50);
  128. },
  129. data() {
  130. return {
  131. winWidth: 0,
  132. scrollLeft: 0
  133. };
  134. },
  135. methods: {
  136. checkCor: function() {
  137. let tabsNum = this.tabs.length
  138. let padding = this.winWidth / 750 * this.padding
  139. let width = this.winWidth - padding * 2
  140. let left = (width / tabsNum - (this.winWidth / 750 * this.sliderWidth)) / 2 + padding
  141. let scrollLeft = left
  142. if (this.currentTab > 0) {
  143. scrollLeft = scrollLeft + (width / tabsNum) * this.currentTab
  144. }
  145. this.scrollLeft = scrollLeft
  146. },
  147. // 点击标题切换当前页时改变样式
  148. swichTabs: function(index) {
  149. let item = this.tabs[index]
  150. if (item && item.disabled) return;
  151. if (this.currentTab == index) {
  152. return false;
  153. } else {
  154. this.$emit("change", {
  155. index: Number(index)
  156. })
  157. }
  158. }
  159. }
  160. }
  161. </script>
  162. <style>
  163. .tui-tabs-view {
  164. width: 100%;
  165. box-sizing: border-box;
  166. display: flex;
  167. align-items: center;
  168. justify-content: space-between;
  169. z-index: 9999;
  170. }
  171. .tui-tabs-relative {
  172. position: relative;
  173. }
  174. .tui-tabs-fixed {
  175. position: fixed;
  176. left: 0;
  177. }
  178. .tui-tabs-fixed::before,
  179. .tui-tabs-relative::before {
  180. content: '';
  181. position: absolute;
  182. border-bottom: 1upx solid #eaeef1;
  183. -webkit-transform: scaleY(0.5);
  184. transform: scaleY(0.5);
  185. bottom: 0;
  186. right: 0;
  187. left: 0;
  188. }
  189. .tui-unlined::before {
  190. border-bottom: 0 !important
  191. }
  192. .tui-tabs-item {
  193. display: flex;
  194. align-items: center;
  195. justify-content: center;
  196. }
  197. .tui-tabs-disabled {
  198. opacity: .6;
  199. }
  200. .tui-tabs-title {
  201. display: flex;
  202. align-items: center;
  203. justify-content: center;
  204. position: relative;
  205. z-index: 2;
  206. }
  207. .tui-tabs-active {
  208. transition: all 0.15s ease-in-out;
  209. }
  210. .tui-tabs-slider {
  211. position: absolute;
  212. left: 0;
  213. transition: all 0.15s ease-in-out;
  214. z-index: 0;
  215. transform: translateZ(0);
  216. }
  217. </style>