Sanakey
2021-01-31 53cc6f817625897935fb10c3845ad7be400f3036
提交 | 用户 | age
d98d05 1 import { VantComponent } from '../common/component';
53cc6f 2 import { isDef } from '../common/validator';
d98d05 3 const LONG_PRESS_START_TIME = 600;
S 4 const LONG_PRESS_INTERVAL = 200;
5 // add num and avoid float number
6 function add(num1, num2) {
7   const cardinal = Math.pow(10, 10);
8   return Math.round((num1 + num2) * cardinal) / cardinal;
9 }
10 function equal(value1, value2) {
11   return String(value1) === String(value2);
12 }
13 VantComponent({
14   field: true,
15   classes: ['input-class', 'plus-class', 'minus-class'],
16   props: {
17     value: {
18       type: null,
19       observer(value) {
20         if (!equal(value, this.data.currentValue)) {
21           this.setData({ currentValue: this.format(value) });
22         }
23       },
24     },
25     integer: {
26       type: Boolean,
27       observer: 'check',
28     },
29     disabled: Boolean,
53cc6f 30     inputWidth: String,
S 31     buttonSize: String,
d98d05 32     asyncChange: Boolean,
S 33     disableInput: Boolean,
34     decimalLength: {
35       type: Number,
36       value: null,
37       observer: 'check',
38     },
39     min: {
40       type: null,
41       value: 1,
42       observer: 'check',
43     },
44     max: {
45       type: null,
46       value: Number.MAX_SAFE_INTEGER,
47       observer: 'check',
48     },
49     step: {
50       type: null,
51       value: 1,
52     },
53     showPlus: {
54       type: Boolean,
55       value: true,
56     },
57     showMinus: {
58       type: Boolean,
59       value: true,
60     },
61     disablePlus: Boolean,
62     disableMinus: Boolean,
63     longPress: {
64       type: Boolean,
65       value: true,
66     },
67   },
68   data: {
69     currentValue: '',
70   },
71   created() {
72     this.setData({
73       currentValue: this.format(this.data.value),
74     });
75   },
76   methods: {
77     check() {
78       const val = this.format(this.data.currentValue);
79       if (!equal(val, this.data.currentValue)) {
80         this.setData({ currentValue: val });
81       }
82     },
83     isDisabled(type) {
84       if (type === 'plus') {
85         return (
86           this.data.disabled ||
87           this.data.disablePlus ||
88           this.data.currentValue >= this.data.max
89         );
90       }
91       return (
92         this.data.disabled ||
93         this.data.disableMinus ||
94         this.data.currentValue <= this.data.min
95       );
96     },
97     onFocus(event) {
98       this.$emit('focus', event.detail);
99     },
100     onBlur(event) {
101       const value = this.format(event.detail.value);
102       this.emitChange(value);
103       this.$emit(
104         'blur',
105         Object.assign(Object.assign({}, event.detail), { value })
106       );
107     },
108     // filter illegal characters
109     filter(value) {
110       value = String(value).replace(/[^0-9.-]/g, '');
111       if (this.data.integer && value.indexOf('.') !== -1) {
112         value = value.split('.')[0];
113       }
114       return value;
115     },
116     // limit value range
117     format(value) {
118       value = this.filter(value);
119       // format range
120       value = value === '' ? 0 : +value;
121       value = Math.max(Math.min(this.data.max, value), this.data.min);
122       // format decimal
123       if (isDef(this.data.decimalLength)) {
124         value = value.toFixed(this.data.decimalLength);
125       }
126       return value;
127     },
128     onInput(event) {
129       const { value = '' } = event.detail || {};
130       // allow input to be empty
131       if (value === '') {
132         return;
133       }
134       let formatted = this.filter(value);
135       // limit max decimal length
136       if (isDef(this.data.decimalLength) && formatted.indexOf('.') !== -1) {
137         const pair = formatted.split('.');
138         formatted = `${pair[0]}.${pair[1].slice(0, this.data.decimalLength)}`;
139       }
140       this.emitChange(formatted);
141     },
142     emitChange(value) {
143       if (!this.data.asyncChange) {
144         this.setData({ currentValue: value });
145       }
146       this.$emit('change', value);
147     },
148     onChange() {
149       const { type } = this;
150       if (this.isDisabled(type)) {
151         this.$emit('overlimit', type);
152         return;
153       }
154       const diff = type === 'minus' ? -this.data.step : +this.data.step;
155       const value = this.format(add(+this.data.currentValue, diff));
156       this.emitChange(value);
157       this.$emit(type);
158     },
159     longPressStep() {
160       this.longPressTimer = setTimeout(() => {
161         this.onChange();
162         this.longPressStep();
163       }, LONG_PRESS_INTERVAL);
164     },
165     onTap(event) {
166       const { type } = event.currentTarget.dataset;
167       this.type = type;
168       this.onChange();
169     },
170     onTouchStart(event) {
171       if (!this.data.longPress) {
172         return;
173       }
174       clearTimeout(this.longPressTimer);
175       const { type } = event.currentTarget.dataset;
176       this.type = type;
177       this.isLongPress = false;
178       this.longPressTimer = setTimeout(() => {
179         this.isLongPress = true;
180         this.onChange();
181         this.longPressStep();
182       }, LONG_PRESS_START_TIME);
183     },
184     onTouchEnd() {
185       if (!this.data.longPress) {
186         return;
187       }
188       clearTimeout(this.longPressTimer);
189     },
190   },
191 });