tui-tabs.vue 4.6 KB

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