tabs.vue 6.6 KB

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