tui-tabs.vue 5.4 KB

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