tabs.vue 5.6 KB

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