uni-segmented-control.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <template>
  2. <view
  3. :class="[
  4. styleType === 'text'
  5. ? 'segmented-control--text'
  6. : 'segmented-control--button',
  7. ]"
  8. :style="{ borderColor: styleType === 'text' ? '' : activeColor, gap: !flex ? '20rpx':0 }"
  9. class="segmented-control"
  10. >
  11. <view
  12. v-for="(item, index) in values"
  13. :class="[
  14. styleType === 'text' ? '' : 'segmented-control__item--button',
  15. index === 0 && styleType === 'button'
  16. ? 'segmented-control__item--button--first'
  17. : '',
  18. index === values.length - 1 && styleType === 'button'
  19. ? 'segmented-control__item--button--last'
  20. : '',
  21. ]"
  22. :key="index"
  23. :style="{
  24. backgroundColor:
  25. index === currentIndex && styleType === 'button'
  26. ? activeColor
  27. : styleType === 'button'
  28. ? inActiveColor
  29. : 'transparent',
  30. borderColor:
  31. (index === currentIndex && styleType === 'text') ||
  32. styleType === 'button'
  33. ? activeColor
  34. : inActiveColor,
  35. flex: flex ? 1 : '',
  36. }"
  37. class="segmented-control__item"
  38. @click="_onClick(index)"
  39. >
  40. <view>
  41. <text
  42. :style="{
  43. color:
  44. index === currentIndex
  45. ? styleType === 'text'
  46. ? activeColor
  47. : '#fff'
  48. : styleType === 'text'
  49. ? '#000'
  50. : activeColor,
  51. }"
  52. class="segmented-control__text"
  53. :class="
  54. styleType === 'text' && index === currentIndex
  55. ? 'segmented-control__item--text'
  56. : ''
  57. "
  58. >{{ item }}</text
  59. >
  60. </view>
  61. </view>
  62. </view>
  63. </template>
  64. <script>
  65. /**
  66. * SegmentedControl 分段器
  67. * @description 用作不同视图的显示
  68. * @tutorial https://ext.dcloud.net.cn/plugin?id=54
  69. * @property {Number} current 当前选中的tab索引值,从0计数
  70. * @property {String} styleType = [button|text] 分段器样式类型
  71. * @value button 按钮类型
  72. * @value text 文字类型
  73. * @property {String} activeColor 选中的标签背景色与边框颜色
  74. * @property {String} inActiveColor 未选中的标签背景色与边框颜色
  75. * @property {Array} values 选项数组
  76. * @event {Function} clickItem 组件触发点击事件时触发,e={currentIndex}
  77. */
  78. export default {
  79. name: "UniSegmentedControl",
  80. emits: ["clickItem"],
  81. props: {
  82. current: {
  83. type: Number,
  84. default: 0,
  85. },
  86. values: {
  87. type: Array,
  88. default() {
  89. return [];
  90. },
  91. },
  92. activeColor: {
  93. type: String,
  94. default: "#2979FF",
  95. },
  96. inActiveColor: {
  97. type: String,
  98. default: "transparent",
  99. },
  100. styleType: {
  101. type: String,
  102. default: "button",
  103. },
  104. flex: {
  105. type: Boolean,
  106. default: true,
  107. }
  108. },
  109. data() {
  110. return {
  111. currentIndex: 0,
  112. };
  113. },
  114. watch: {
  115. current(val) {
  116. if (val !== this.currentIndex) {
  117. this.currentIndex = val;
  118. }
  119. },
  120. },
  121. computed: {},
  122. created() {
  123. this.currentIndex = this.current;
  124. },
  125. methods: {
  126. _onClick(index) {
  127. if (this.currentIndex !== index) {
  128. this.currentIndex = index;
  129. this.$emit("clickItem", {
  130. currentIndex: index,
  131. });
  132. }
  133. },
  134. },
  135. };
  136. </script>
  137. <style lang="scss" scoped>
  138. .segmented-control {
  139. /* #ifndef APP-NVUE */
  140. display: flex;
  141. box-sizing: border-box;
  142. /* #endif */
  143. flex-direction: row;
  144. height: 36px;
  145. overflow: hidden;
  146. /* #ifdef H5 */
  147. cursor: pointer;
  148. /* #endif */
  149. }
  150. .segmented-control__item {
  151. /* #ifndef APP-NVUE */
  152. display: inline-flex;
  153. box-sizing: border-box;
  154. /* #endif */
  155. position: relative;
  156. justify-content: center;
  157. align-items: center;
  158. }
  159. .segmented-control__item--button {
  160. border-style: solid;
  161. border-top-width: 1px;
  162. border-bottom-width: 1px;
  163. border-right-width: 1px;
  164. border-left-width: 0;
  165. }
  166. .segmented-control__item--button--first {
  167. border-left-width: 1px;
  168. border-top-left-radius: 5px;
  169. border-bottom-left-radius: 5px;
  170. }
  171. .segmented-control__item--button--last {
  172. border-top-right-radius: 5px;
  173. border-bottom-right-radius: 5px;
  174. }
  175. .segmented-control__item--text {
  176. border-bottom-style: solid;
  177. border-bottom-width: 2px;
  178. padding: 6px 0;
  179. }
  180. .segmented-control__text {
  181. font-size: 14px;
  182. line-height: 20px;
  183. text-align: center;
  184. }
  185. </style>