tui-tabs.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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:backgroundColor,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. backgroundColor: {
  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: "#C74547"
  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: "#C74547"
  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. tabs() {
  118. this.checkCor();
  119. }
  120. },
  121. created() {
  122. setTimeout(() => {
  123. // 高度自适应
  124. uni.getSystemInfo({
  125. success: (res) => {
  126. this.winWidth = res.windowWidth;
  127. this.checkCor()
  128. }
  129. });
  130. }, 50);
  131. },
  132. data() {
  133. return {
  134. winWidth: 0,
  135. scrollLeft: 0
  136. };
  137. },
  138. methods: {
  139. checkCor: function() {
  140. let tabsNum = this.tabs.length
  141. let padding = this.winWidth / 750 * this.padding
  142. let width = this.winWidth - padding * 2
  143. let left = (width / tabsNum - (this.winWidth / 750 * this.sliderWidth)) / 2 + padding
  144. let scrollLeft = left
  145. if (this.currentTab > 0) {
  146. scrollLeft = scrollLeft + (width / tabsNum) * this.currentTab
  147. }
  148. this.scrollLeft = scrollLeft
  149. },
  150. // 点击标题切换当前页时改变样式
  151. swichTabs: function(index) {
  152. let item = this.tabs[index]
  153. if (item && item.disabled) return;
  154. if (this.currentTab == index) {
  155. return false;
  156. } else {
  157. this.$emit("change", {
  158. index: Number(index)
  159. })
  160. }
  161. }
  162. }
  163. }
  164. </script>
  165. <style scoped>
  166. .tui-tabs-view {
  167. width: 100%;
  168. box-sizing: border-box;
  169. display: flex;
  170. align-items: center;
  171. justify-content: space-between;
  172. z-index: 996;
  173. }
  174. .tui-tabs-relative {
  175. position: relative;
  176. }
  177. .tui-tabs-fixed {
  178. position: fixed;
  179. left: 0;
  180. }
  181. .tui-tabs-fixed::before,
  182. .tui-tabs-relative::before {
  183. content: '';
  184. position: absolute;
  185. border-bottom: 1rpx solid #eaeef1;
  186. -webkit-transform: scaleY(0.5) translateZ(0);
  187. transform: scaleY(0.5) translateZ(0);
  188. transform-origin: 0 100%;
  189. bottom: 0;
  190. right: 0;
  191. left: 0;
  192. }
  193. .tui-unlined::before {
  194. border-bottom: 0 !important
  195. }
  196. .tui-tabs-item {
  197. display: flex;
  198. align-items: center;
  199. justify-content: center;
  200. }
  201. .tui-tabs-disabled {
  202. opacity: .6;
  203. }
  204. .tui-tabs-title {
  205. display: flex;
  206. align-items: center;
  207. justify-content: center;
  208. position: relative;
  209. z-index: 2;
  210. }
  211. .tui-tabs-active {
  212. transition: all 0.15s ease-in-out;
  213. }
  214. .tui-tabs-slider {
  215. position: absolute;
  216. left: 0;
  217. transition: all 0.15s ease-in-out;
  218. z-index: 0;
  219. transform: translateZ(0);
  220. }
  221. </style>