cl-input-number.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <template>
  2. <view class="cl-input-number">
  3. <!-- 减 -->
  4. <button class="cl-input-number__minus" @tap="onMinus">
  5. <text class="cl-icon-minus"></text>
  6. </button>
  7. <!-- 值 -->
  8. <view class="cl-input-number__value" :style="{ width: width2 }">
  9. <input type="number" v-model="value2" @blur="onBlur" v-if="input" />
  10. <text v-else>{{ value2 }}</text>
  11. </view>
  12. <!-- 加 -->
  13. <button class="cl-input-number__plus" @tap="onPlus">
  14. <text class="cl-icon-plus"></text>
  15. </button>
  16. </view>
  17. </template>
  18. <script>
  19. /**
  20. * input-number 计数器
  21. * @description 仅允许操作标准的数字值,可定义范围
  22. * @tutorial https://docs.cool-js.com/uni/components/form/input-number.html
  23. * @property {null} value 绑定值
  24. * @property {Numbder} step 步进,默认1
  25. * @property {Numbder} max 最大值,默认100
  26. * @property {Numbder} min 最小值,默认0
  27. * @property {Boolean} input 是否能编辑,默认false
  28. * @property {Numbder} width 输入框宽度,默认100
  29. * @property {Numbder} precision 数值精度
  30. * @event {Function} change 绑定值改变时触发
  31. * @example <cl-input-number v-model="val" />
  32. */
  33. import { parseRpx, isString, isDecimal } from "../../utils";
  34. export default {
  35. name: "cl-input-number",
  36. props: {
  37. // 绑定值
  38. value: {
  39. type: [String, Number],
  40. required: true,
  41. },
  42. // 步进
  43. step: {
  44. type: Number,
  45. default: 1,
  46. },
  47. // 最大值
  48. max: {
  49. type: Number,
  50. default: 100,
  51. },
  52. // 最小值
  53. min: {
  54. type: Number,
  55. default: 0,
  56. },
  57. // 是否能输入
  58. input: {
  59. type: Boolean,
  60. default: false,
  61. },
  62. // 宽度
  63. width: {
  64. type: Number,
  65. default: 100,
  66. },
  67. // 小数
  68. precision: Number,
  69. },
  70. data() {
  71. return {
  72. value2: 0,
  73. };
  74. },
  75. computed: {
  76. width2() {
  77. return this.input ? parseRpx(this.width) : "auto";
  78. },
  79. },
  80. watch: {
  81. value: {
  82. immediate: true,
  83. handler(val) {
  84. this.check(val);
  85. },
  86. },
  87. max: {
  88. handler() {
  89. this.update();
  90. },
  91. },
  92. min: {
  93. handler() {
  94. this.update();
  95. },
  96. },
  97. },
  98. methods: {
  99. // 验证值
  100. check(val) {
  101. if (val === undefined) {
  102. val = this.value2;
  103. }
  104. // 是否字符
  105. if (isString(val)) {
  106. val = Number(val);
  107. }
  108. // 是否小数
  109. if (isDecimal(val)) {
  110. val = Number(val.toFixed(this.precision || 0));
  111. }
  112. // 最小
  113. if (val < this.min) {
  114. val = this.min;
  115. }
  116. // 最大
  117. if (val > this.max) {
  118. val = this.max;
  119. }
  120. // 最小不能超过最大
  121. if (this.min > this.max) {
  122. val = this.max;
  123. }
  124. this.value2 = val;
  125. },
  126. // 更新值
  127. update() {
  128. this.check();
  129. this.$emit("input", this.value2);
  130. this.$emit("change", this.value2);
  131. },
  132. onPlus() {
  133. this.value2 += this.step;
  134. if (this.value2 > this.max && this.max !== Infinity) {
  135. this.value2 = this.max;
  136. }
  137. this.update();
  138. },
  139. onMinus() {
  140. this.value2 -= this.step;
  141. if (this.value2 < this.min && this.min !== Infinity) {
  142. this.value2 = this.min;
  143. }
  144. this.update();
  145. },
  146. onBlur() {
  147. this.update();
  148. },
  149. },
  150. };
  151. </script>