uni-number-box.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <template>
  2. <view class="uni-numbox">
  3. <view :class="{'uni-numbox--disabled': inputValue <= min || disabled}" class="uni-numbox__minus" @click="_calcValue('minus')">-</view>
  4. <input :disabled="disabled" v-model="inputValue" class="uni-numbox__value" type="number" @blur="_onBlur">
  5. <view :class="{'uni-numbox--disabled': inputValue >= max || disabled}" class="uni-numbox__plus" @click="_calcValue('plus')">+</view>
  6. </view>
  7. </template>
  8. <script>
  9. export default {
  10. name: 'UniNumberBox',
  11. props: {
  12. value: {
  13. type: [Number, String],
  14. default: 1
  15. },
  16. min: {
  17. type: Number,
  18. default: 0
  19. },
  20. max: {
  21. type: Number,
  22. default: 100
  23. },
  24. step: {
  25. type: Number,
  26. default: 1
  27. },
  28. disabled: {
  29. type: Boolean,
  30. default: false
  31. }
  32. },
  33. data() {
  34. return {
  35. inputValue: 0
  36. }
  37. },
  38. watch: {
  39. value(val) {
  40. this.inputValue = +val
  41. },
  42. inputValue(newVal, oldVal) {
  43. if (+newVal !== +oldVal) {
  44. this.$emit('change', newVal)
  45. }
  46. }
  47. },
  48. created() {
  49. this.inputValue = +this.value
  50. },
  51. methods: {
  52. _calcValue(type) {
  53. if (this.disabled) {
  54. return
  55. }
  56. const scale = this._getDecimalScale()
  57. let value = this.inputValue * scale
  58. let step = this.step * scale
  59. if (type === 'minus') {
  60. value -= step
  61. } else if (type === 'plus') {
  62. value += step
  63. }
  64. if (value < this.min || value > this.max) {
  65. return
  66. }
  67. this.inputValue = value / scale
  68. },
  69. _getDecimalScale() {
  70. let scale = 1
  71. // 浮点型
  72. if (~~this.step !== this.step) {
  73. scale = Math.pow(10, (this.step + '').split('.')[1].length)
  74. }
  75. return scale
  76. },
  77. _onBlur(event) {
  78. let value = event.detail.value
  79. if (!value) {
  80. this.inputValue = 0
  81. return
  82. }
  83. value = +value
  84. if (value > this.max) {
  85. value = this.max
  86. } else if (value < this.min) {
  87. value = this.min
  88. }
  89. this.inputValue = value
  90. }
  91. }
  92. }
  93. </script>
  94. <style>
  95. @charset "UTF-8";
  96. .uni-numbox {
  97. display: inline-flex;
  98. flex-direction: row;
  99. justify-content: flex-start;
  100. height: 70upx;
  101. position: relative
  102. }
  103. .uni-numbox:after {
  104. content: '';
  105. position: absolute;
  106. transform-origin: center;
  107. box-sizing: border-box;
  108. pointer-events: none;
  109. top: -50%;
  110. left: -50%;
  111. right: -50%;
  112. bottom: -50%;
  113. border: 1px solid #c8c7cc;
  114. border-radius: 12upx;
  115. transform: scale(.5)
  116. }
  117. .uni-numbox__minus,
  118. .uni-numbox__plus {
  119. margin: 0;
  120. background-color: #f8f8f8;
  121. width: 70upx;
  122. font-size: 40upx;
  123. height: 100%;
  124. line-height: 70upx;
  125. text-align: center;
  126. display: inline-flex;
  127. align-items: center;
  128. justify-content: center;
  129. color: #333;
  130. position: relative
  131. }
  132. .uni-numbox__value {
  133. position: relative;
  134. background-color: #fff;
  135. width: 80upx;
  136. height: 100%;
  137. text-align: center;
  138. padding: 0
  139. }
  140. .uni-numbox__value:after {
  141. content: '';
  142. position: absolute;
  143. transform-origin: center;
  144. box-sizing: border-box;
  145. pointer-events: none;
  146. top: -50%;
  147. left: -50%;
  148. right: -50%;
  149. bottom: -50%;
  150. border-style: solid;
  151. border-color: #c8c7cc;
  152. border-left-width: 1px;
  153. border-right-width: 1px;
  154. border-top-width: 0;
  155. border-bottom-width: 0;
  156. transform: scale(.5)
  157. }
  158. .uni-numbox--disabled {
  159. color: silver
  160. }
  161. </style>