index.taro.vue 4.1 KB

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