zzx-tabs.vue 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <template>
  2. <view class="zzx-tabs">
  3. <view class="zzx-tabs-wrap">
  4. <view class="zzx-tab" v-for="(item,index) in items" :key="index" @click="_onClick(index)"
  5. :style="{
  6. width: iwidth,
  7. color: index === currentIndex ? activeColor : defaultColor
  8. }"
  9. >
  10. <slot v-bind:item="item">
  11. <text class="item-title" :class="dots[index] ? 'dot-show' : ''">{{item}}</text>
  12. </slot>
  13. </view>
  14. </view>
  15. <view class="zzx-tabs-bar" :style="{
  16. width: iwidth,
  17. transform: moveDistance,
  18. marginTop: lineTop
  19. }">
  20. <view class="zzx-bottom-line"
  21. :style="{
  22. height: lineHeight,
  23. width: lineWidth,
  24. background: activeColor
  25. }"
  26. >
  27. </view>
  28. </view>
  29. </view>
  30. </template>
  31. <script>
  32. export default {
  33. props: {
  34. items: {
  35. type: Array,
  36. default() {
  37. return ['已完成', '未完成']
  38. }
  39. },
  40. current: {
  41. type: Number,
  42. default: 0
  43. },
  44. defaultColor: {
  45. type: String,
  46. default: '#999999'
  47. },
  48. activeColor: {
  49. type: String,
  50. default: '#FF6633'
  51. },
  52. tabHeight: {
  53. type: String,
  54. default: '60upx'
  55. },
  56. lineHeight: {
  57. type: String,
  58. default: '3px'
  59. },
  60. lineWidth: {
  61. type: String,
  62. default: '40%'
  63. },
  64. lineTop: {
  65. type: String,
  66. default: '0px'
  67. }
  68. },
  69. computed: {
  70. iwidth() {
  71. const num = this.items.length;
  72. let w = '100%';
  73. if (num > 0) {
  74. w = (100 / num) + '%';
  75. }
  76. return w;
  77. },
  78. moveDistance() {
  79. let d = '';
  80. d = this.currentIndex * 100 + '%'
  81. return `translate3d(${d}, 0, 0)`;
  82. }
  83. },
  84. watch: {
  85. current(newIndex) {
  86. if (newIndex !== this.currentIndex) {
  87. this.currentIndex = newIndex
  88. }
  89. }
  90. },
  91. data() {
  92. return {
  93. currentIndex: 0,
  94. dots: []
  95. };
  96. },
  97. created() {
  98. this.currentIndex = this.current
  99. this.dots = Array(this.items.length).fill(0)
  100. },
  101. methods: {
  102. _onClick(index) {
  103. if (this.currentIndex !== index) {
  104. this.currentIndex = index
  105. this.$emit('clickItem', {currentIndex:index})
  106. }
  107. },
  108. setDot(index) {
  109. // 设置红点标记
  110. if (index>=0 && index <this.dots.length) {
  111. // 如果本来就是1的话就不需要修改
  112. if (!this.dots[index]) {
  113. this.dots.splice(index, 1, 1);
  114. }
  115. }
  116. },
  117. removeDot(index) {
  118. // 取消红点标记
  119. if (index>=0 && index <this.dots.length) {
  120. if (this.dots[index]) {
  121. this.dots.splice(index, 1, 0);
  122. }
  123. }
  124. }
  125. }
  126. }
  127. </script>
  128. <style lang="scss">
  129. .zzx-tabs {
  130. .zzx-tabs-wrap {
  131. width: 100%;
  132. display: flex;
  133. flex-flow: row nowrap;
  134. justify-content: flex-start;
  135. font-size: 14px;
  136. box-sizing: border-box;
  137. height: 60upx;
  138. line-height: 60upx;
  139. .zzx-tab {
  140. box-sizing: border-box;
  141. text-align: center;
  142. color: #999999;
  143. }
  144. .item-title {
  145. position: relative;
  146. }
  147. .dot-show {
  148. &:after {
  149. display: inline-block;
  150. content: '';
  151. width: 5px;
  152. height: 5px;
  153. position: absolute;
  154. background: #ff0000;
  155. border-radius: 50%;
  156. right: -15upx;
  157. top: -8upx;
  158. }
  159. }
  160. }
  161. .zzx-tabs-bar {
  162. display: flex;
  163. justify-content: center;
  164. transform-origin: 0 0;
  165. transform: translate3d(100%, 0, 0);
  166. transition-property: all;
  167. transition-timing-function: cubic-bezier (0.645, 0.045, 0.355, 1);
  168. transition-duration: 0.1s;
  169. .zzx-bottom-line {
  170. height: 2px;
  171. background-color: #FF6633;
  172. width: 40%;
  173. }
  174. }
  175. }
  176. </style>