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