您的真正问题在于,您将从this.value
读取的值赋给了this.value
。所得到的字符串并不完全等同于用户实际输入的内容。例如,如果用户输入了“1.”,您得到的是解析后的值“1”,而不包含后面的句点。由于您将这个值重新赋给控件,而这个值的长度比当前值短,控件当前位置信息就会丢失,被重置为0,即控件的起始位置。这就是为什么当您输入小数点分隔符时,光标会跳到第一个位置的原因。
如果输入包含无效字符,则返回空字符串。Chrome 和 Edge 会对允许使用的字符进行过滤。而 Firefox 不会。Chrome 允许使用小数点和小数逗号作为小数分隔符,但返回的值始终使用小数点。
您可以在此下方测试:
<input id="wrong" type="number" oninput="console.log(this.value)" />
由于type="number"
输入框的行为取决于具体的浏览器,通常我会将其类型设为"text"。这样,如果浏览器支持,maxlength
属性会被遵守,而且您无需修改元素本身。您可以在代码中读取值时进行解析。
<script>
const elem = document.querySelector('input[name=usernumber]');
// 只允许输入数字和小数点
elem.addEventListener('beforeinput', (event) => {
const key = event.data;
if (!((key === '.' && elem.value.indexOf('.') < 0) || (key >= '0' && key <= '9'))) event.preventDefault();
// 您可以添加其他检查
});
// 解析输入值
elem.addEventListener('input', (event) => {
console.log('The value', parseFloat(elem.value))
});
</script>
<style>
input:invalid {
background-color: red;
}
</style>
<input name="usernumber" type="text" inputmode="numeric" pattern="\d*(\.\d*)?" maxlength="5" />
inputmode="numeric"
是向浏览器提供的一种提示,表明应显示何种键盘。
pattern="\d*(\.\d*)?"
告诉浏览器什么样的输入是有效的。注意:您仍然可以输入非法字符,此时字段会被标记为无效,您可以借助一些CSS样式来显示这一点。