我刚刚遇到了同样的问题,并发现了一个使用验证 API 的替代解决方案——在除 IE 之外的所有主要浏览器(Chrome、Firefox、Safari)中都没有黑魔法。此解决方案只是防止用户输入无效值。我还包括了一个 IE 的后备,虽然不好但至少可以工作。
上下文:onInput函数在输入事件上调用,setInputValue用于设置输入元素的值,previousInputValue包含最后一个有效输入值(在 setInputValue 调用中更新)。
function onInput (event) {
const inputValue = event.target.value;
// badInput supported on validation api (except IE)
// in IE it will be undefined, so we need strict value check
const badInput = event.target.validity.badInput;
// simply prevent modifying the value
if (badInput === true) {
// it's still possible to enter invalid values in an empty input, so we'll need this trick to prevent that
if (previousInputValue === '') {
setInputValue(' ');
setTimeout(() => {
setInputValue('');
}, 1);
}
return;
}
if (badInput === false) {
setInputValue(inputValue);
return;
}
// fallback case for IE and other abominations
// remove everything from the string expect numbers, point and comma
// replace comma with points (parseFloat works only with points)
let stringVal = String(inputValue)
.replace(/([^0-9.,])/g, '')
.replace(/,/g, '.');
// remove all but first point
const pointIndex = stringVal.indexOf('.');
if (pointIndex !== -1) {
const pointAndBefore = stringVal.substring(0, pointIndex + 1);
const afterPoint = stringVal.substring(pointIndex + 1);
// removing all points after the first
stringVal = `${pointAndBefore}${afterPoint.replace(/\./g, '')}`;
}
const float = parseFloat(stringVal);
if (isNaN(float)) {
// fallback to emptying the input if anything goes south
setInputValue('');
return;
}
setInputValue(stringVal);
}