uni-number-box.vue 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <template>
  2. <view class="uni-numbox">
  3. <view class="uni-numbox-minus" :class="{'uni-numbox-disabled': disableSubtract}" @click="_calcValue('subtract')">-</view>
  4. <input class="uni-numbox-value" type="number" :disabled="disabled" :value="inputValue" @blur="_onBlur">
  5. <view class="uni-numbox-plus" :class="{'uni-numbox-disabled': disableAdd}" @click="_calcValue('add')">+</view>
  6. </view>
  7. </template>
  8. <script>
  9. export default {
  10. name: 'uni-number-box',
  11. props: {
  12. value: {
  13. type: Number,
  14. default: 0
  15. },
  16. min: {
  17. type: Number,
  18. default: -Infinity
  19. },
  20. max: {
  21. type: Number,
  22. default: Infinity
  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: this.value
  36. }
  37. },
  38. computed: {
  39. disableSubtract() {
  40. return this.value <= this.min
  41. },
  42. disableAdd() {
  43. return this.value >= this.max
  44. }
  45. },
  46. watch: {
  47. value(val) {
  48. this.inputValue = val;
  49. },
  50. inputValue(val) {
  51. this.$emit('change', val);
  52. }
  53. },
  54. methods: {
  55. _calcValue(type) {
  56. const scale = this._getDecimalScale();
  57. let value = this.inputValue * scale;
  58. let step = this.step * scale;
  59. if (type === 'subtract') {
  60. value -= step
  61. } else if (type === 'add') {
  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. .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. transform: scale(.5);
  114. }
  115. .uni-numbox-minus,
  116. .uni-numbox-plus {
  117. margin: 0;
  118. background-color: #f9f9f9;
  119. width: 80upx;
  120. height: 100%;
  121. line-height: 70upx;
  122. text-align: center;
  123. color: #555555;
  124. position: relative;
  125. }
  126. .uni-numbox-minus {
  127. border-right: none;
  128. border-top-left-radius: 6upx;
  129. border-bottom-left-radius: 6upx;
  130. }
  131. .uni-numbox-plus {
  132. border-left: none;
  133. border-top-right-radius: 6upx;
  134. border-bottom-right-radius: 6upx;
  135. }
  136. .uni-numbox-value {
  137. position: relative;
  138. background-color: #ffffff;
  139. width: 80upx;
  140. height: 100%;
  141. text-align: center;
  142. padding: 0;
  143. }
  144. .uni-numbox-value::after {
  145. content: '';
  146. position: absolute;
  147. transform-origin: center;
  148. box-sizing: border-box;
  149. pointer-events: none;
  150. top: -50%;
  151. left: -50%;
  152. right: -50%;
  153. bottom: -50%;
  154. border-style: solid;
  155. border-color: #cccccc;
  156. border-left-width: 1px;
  157. border-right-width: 1px;
  158. border-top-width: 0;
  159. border-bottom-width: 0;
  160. transform: scale(.5);
  161. }
  162. .uni-numbox-disabled {
  163. color: #c0c0c0;
  164. }
  165. </style>