uni-number-box.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <template>
  2. <view class="uni-numbox">
  3. <view @click="_calcValue('minus')" class="uni-numbox__minus uni-cursor-point">
  4. <text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }">-</text>
  5. </view>
  6. <input :disabled="disabled" @focus="_onFocus" @blur="_onBlur" class="uni-numbox__value" type="number"
  7. v-model="inputValue" />
  8. <view @click="_calcValue('plus')" class="uni-numbox__plus uni-cursor-point">
  9. <text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }">+</text>
  10. </view>
  11. </view>
  12. </template>
  13. <script>
  14. /**
  15. * NumberBox 数字输入框
  16. * @description 带加减按钮的数字输入框
  17. * @tutorial https://ext.dcloud.net.cn/plugin?id=31
  18. * @property {Number} value 输入框当前值
  19. * @property {Number} min 最小值
  20. * @property {Number} max 最大值
  21. * @property {Number} step 每次点击改变的间隔大小
  22. * @property {Boolean} disabled = [true|false] 是否为禁用状态
  23. * @event {Function} change 输入框值改变时触发的事件,参数为输入框当前的 value
  24. */
  25. export default {
  26. name: "UniNumberBox",
  27. props: {
  28. value: {
  29. type: [Number, String],
  30. default: 1
  31. },
  32. min: {
  33. type: Number,
  34. default: 0
  35. },
  36. max: {
  37. type: Number,
  38. default: 100
  39. },
  40. step: {
  41. type: Number,
  42. default: 1
  43. },
  44. disabled: {
  45. type: Boolean,
  46. default: false
  47. }
  48. },
  49. data() {
  50. return {
  51. inputValue: 0
  52. };
  53. },
  54. watch: {
  55. value(val) {
  56. this.inputValue = +val;
  57. }
  58. },
  59. created() {
  60. this.inputValue = +this.value;
  61. },
  62. methods: {
  63. _calcValue(type) {
  64. if (this.disabled) {
  65. return;
  66. }
  67. const scale = this._getDecimalScale();
  68. let value = this.inputValue * scale;
  69. let step = this.step * scale;
  70. if (type === "minus") {
  71. value -= step;
  72. if (value < (this.min * scale)) {
  73. return;
  74. }
  75. if (value > (this.max * scale)) {
  76. value = this.max * scale
  77. }
  78. }
  79. if (type === "plus") {
  80. value += step;
  81. if (value > (this.max * scale)) {
  82. return;
  83. }
  84. if (value < (this.min * scale)) {
  85. value = this.min * scale
  86. }
  87. }
  88. this.inputValue = (value / scale).toFixed(String(scale).length - 1);
  89. this.$emit("change", +this.inputValue);
  90. this.$emit("input", +this.inputValue);
  91. },
  92. _getDecimalScale() {
  93. let scale = 1;
  94. // 浮点型
  95. if (~~this.step !== this.step) {
  96. scale = Math.pow(10, String(this.step).split(".")[1].length);
  97. }
  98. return scale;
  99. },
  100. _onBlur(event) {
  101. this.$emit('blur', event)
  102. let value = event.detail.value;
  103. if (!value) {
  104. // this.inputValue = 0;
  105. return;
  106. }
  107. value = +value;
  108. if (value > this.max) {
  109. value = this.max;
  110. } else if (value < this.min) {
  111. value = this.min;
  112. }
  113. const scale = this._getDecimalScale();
  114. this.inputValue = value.toFixed(String(scale).length - 1);
  115. this.$emit("change", +this.inputValue);
  116. this.$emit("input", +this.inputValue);
  117. },
  118. _onFocus(event) {
  119. this.$emit('focus', event)
  120. }
  121. }
  122. };
  123. </script>
  124. <style lang="scss" scoped>
  125. $box-height: 35px;
  126. /* #ifdef APP-NVUE */
  127. $box-line-height: 35px;
  128. /* #endif */
  129. $box-line-height: 26px;
  130. $box-width: 35px;
  131. .uni-numbox {
  132. /* #ifndef APP-NVUE */
  133. display: flex;
  134. /* #endif */
  135. flex-direction: row;
  136. height: $box-height;
  137. line-height: $box-height;
  138. width: 120px;
  139. }
  140. .uni-cursor-point {
  141. /* #ifdef H5 */
  142. cursor: pointer;
  143. /* #endif */
  144. }
  145. .uni-numbox__value {
  146. background-color: $uni-bg-color;
  147. width: 50px;
  148. height: $box-height;
  149. text-align: center;
  150. font-size: $uni-font-size-lg;
  151. border-width: 1rpx;
  152. border-style: solid;
  153. border-color: $uni-border-color;
  154. border-left-width: 0;
  155. border-right-width: 0;
  156. }
  157. .uni-numbox__minus {
  158. /* #ifndef APP-NVUE */
  159. display: flex;
  160. /* #endif */
  161. flex-direction: row;
  162. align-items: center;
  163. justify-content: center;
  164. width: $box-width;
  165. height: $box-height;
  166. // line-height: $box-line-height;
  167. // text-align: center;
  168. font-size: 20px;
  169. color: $uni-text-color;
  170. background-color: $uni-bg-color-grey;
  171. border-width: 1rpx;
  172. border-style: solid;
  173. border-color: $uni-border-color;
  174. border-top-left-radius: $uni-border-radius-base;
  175. border-bottom-left-radius: $uni-border-radius-base;
  176. border-right-width: 0;
  177. }
  178. .uni-numbox__plus {
  179. /* #ifndef APP-NVUE */
  180. display: flex;
  181. /* #endif */
  182. flex-direction: row;
  183. align-items: center;
  184. justify-content: center;
  185. width: $box-width;
  186. height: $box-height;
  187. border-width: 1rpx;
  188. border-style: solid;
  189. border-color: $uni-border-color;
  190. border-top-right-radius: $uni-border-radius-base;
  191. border-bottom-right-radius: $uni-border-radius-base;
  192. background-color: $uni-bg-color-grey;
  193. border-left-width: 0;
  194. }
  195. .uni-numbox--text {
  196. font-size: 20px;
  197. color: $uni-text-color;
  198. }
  199. .uni-numbox--disabled {
  200. color: $uni-text-color-disable;
  201. /* #ifdef H5 */
  202. cursor: not-allowed;
  203. /* #endif */
  204. }
  205. </style>