index.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <view :class="classes" :style="{ height: pxCheck(buttonSize) }">
  3. <nut-icon
  4. name="minus"
  5. class="nut-inputnumber__icon"
  6. :class="{ 'nut-inputnumber__icon--disabled': !reduceAllow() }"
  7. :size="buttonSize"
  8. @click="reduce"
  9. >
  10. </nut-icon>
  11. <input
  12. type="number"
  13. :min="min"
  14. :max="max"
  15. :style="{ width: pxCheck(inputWidth) }"
  16. :disabled="disabled"
  17. :readonly="readonly"
  18. :value="modelValue"
  19. @input="change"
  20. @blur="blur"
  21. @focus="focus"
  22. />
  23. <nut-icon
  24. name="plus"
  25. class="nut-inputnumber__icon"
  26. :class="{ 'nut-inputnumber__icon--disabled': !addAllow() }"
  27. :size="buttonSize"
  28. @click="add"
  29. >
  30. </nut-icon>
  31. </view>
  32. </template>
  33. <script lang="ts">
  34. import { computed } from 'vue';
  35. import { createComponent } from '@/utils/create';
  36. import { pxCheck } from '@/utils/pxCheck';
  37. const { componentName, create } = createComponent('inputnumber');
  38. export default create({
  39. props: {
  40. modelValue: {
  41. type: [Number, String],
  42. default: 0
  43. },
  44. inputWidth: {
  45. type: [Number, String],
  46. default: ''
  47. },
  48. buttonSize: {
  49. type: [Number, String],
  50. default: ''
  51. },
  52. min: {
  53. type: [Number, String],
  54. default: 1
  55. },
  56. max: {
  57. type: [Number, String],
  58. default: 9999
  59. },
  60. step: {
  61. type: [Number, String],
  62. default: 1
  63. },
  64. decimalPlaces: {
  65. type: [Number, String],
  66. default: 0
  67. },
  68. disabled: {
  69. type: Boolean,
  70. default: false
  71. },
  72. readonly: {
  73. type: Boolean,
  74. default: false
  75. }
  76. },
  77. emits: [
  78. 'update:modelValue',
  79. 'change',
  80. 'blur',
  81. 'focus',
  82. 'reduce',
  83. 'add',
  84. 'overlimit'
  85. ],
  86. setup(props, { emit }) {
  87. const classes = computed(() => {
  88. const prefixCls = componentName;
  89. return {
  90. [prefixCls]: true,
  91. [`${prefixCls}--disabled`]: props.disabled
  92. };
  93. });
  94. const fixedDecimalPlaces = (v: string | number): string => {
  95. return Number(v).toFixed(Number(props.decimalPlaces));
  96. };
  97. const change = (event: Event) => {
  98. const input = event.target as HTMLInputElement;
  99. emit('update:modelValue', input.valueAsNumber, event);
  100. };
  101. const emitChange = (value: string | number, event: Event) => {
  102. let output_value: number | string = fixedDecimalPlaces(value);
  103. emit('change', output_value, event);
  104. emit('update:modelValue', output_value, event);
  105. };
  106. const addAllow = (value = Number(props.modelValue)): boolean => {
  107. return value < Number(props.max) && !props.disabled;
  108. };
  109. const reduceAllow = (value = Number(props.modelValue)): boolean => {
  110. return value > Number(props.min) && !props.disabled;
  111. };
  112. const reduce = (event: Event) => {
  113. emit('reduce', event);
  114. if (reduceAllow()) {
  115. let output_value = Number(props.modelValue) - Number(props.step);
  116. emitChange(output_value, event);
  117. } else {
  118. emit('overlimit', event);
  119. }
  120. };
  121. const add = (event: Event) => {
  122. emit('add', event);
  123. if (addAllow()) {
  124. let output_value = Number(props.modelValue) + Number(props.step);
  125. emitChange(output_value, event);
  126. } else {
  127. emit('overlimit', event);
  128. }
  129. };
  130. const focus = (event: Event) => {
  131. if (props.disabled) return;
  132. if (props.readonly) return;
  133. emit('focus', event);
  134. };
  135. const blur = (event: Event) => {
  136. if (props.disabled) return;
  137. if (props.readonly) return;
  138. const input = event.target as HTMLInputElement;
  139. let value = input.valueAsNumber;
  140. if (value < Number(props.min)) {
  141. value = Number(props.min);
  142. } else if (value > Number(props.max)) {
  143. value = Number(props.max);
  144. }
  145. emitChange(value, event);
  146. emit('blur', event);
  147. };
  148. return {
  149. classes,
  150. change,
  151. blur,
  152. focus,
  153. add,
  154. addAllow,
  155. reduce,
  156. reduceAllow,
  157. pxCheck
  158. };
  159. }
  160. });
  161. </script>
  162. <style lang="scss">
  163. @import 'index.scss';
  164. </style>