提交 | 用户 | 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 |
}); |