在 <input type="number">
中,当输入值过小或过大时,浏览器会自动转换为科学计数法(如 -1e-18
),这会影响数据展示和后续计算。以下是 5 种解决方案,帮你彻底规避这个问题!
解决方案
方案 | 实现方式 | 适用场景 | 优点 |
---|---|---|---|
1. 改用 type="text" + 正则校验 |
手动控制数字输入格式 | 需要完全自定义输入行为 | 完全避免科学计数法 |
2. 使用 step 属性限制 |
限制最小输入精度 | 允许小数但需控制范围 | 原生支持,简单易用 |
3. @input 实时格式化 |
在输入时过滤非法字符 | 需要即时反馈输入结果 | 用户体验流畅 |
4. @blur 后格式化 |
在失焦时修正数值 | 允许中间态存在非常规格式 | 减少输入干扰 |
5. 自定义指令 | 全局统一处理数字输入 | 项目中有多处需要相同逻辑 | 一次实现,多处复用 |
推荐方案 1:改用 type="text"
+ 正则校验
原理:通过文本输入框手动控制数字格式,彻底避免科学计数法。
ini
<input
class="inp"
type="text"
pattern="[0-9]*.?[0-9]*" <!-- 只允许数字和小数点 -->
@input="handleNumberInput($event, 'totalServiceFee')"
:value="formData.paymentRoutine.totalServiceFee"
placeholder="请输入服务费"
placeholder-class="inp_placeholder"
/>
JS 处理逻辑:
javascript
methods: {
handleNumberInput(event, field) {
// 过滤非数字字符(允许小数点和负号)
let value = event.target.value.replace(/[^\d.-]/g, '');
// 避免多个小数点或负号
if ((value.match(/./g) || []).length > 1) {
value = value.slice(0, -1);
}
if ((value.match(/-/g) || []).length > 1) {
value = value.replace(/-/g, '').replace(/^(-)?/, '-');
}
// 更新数据(转为数字类型)
this.$set(this.formData.paymentRoutine, field, Number(value));
}
}
推荐方案 2:使用 step
属性限制精度
原理 :通过 step
限制最小输入单位,避免过小数值。
ini
<input
type="number"
step="0.00000001" <!-- 限制最小精度为 0.00000001 -->
min="0" <!-- 禁止负数 -->
v-model="formData.paymentRoutine.totalServiceFee"
@blur="validateFixed($event, 'totalServiceFee')"
/>
推荐方案 3: @input
实时格式化
原理 :在 @input
事件中实时过滤非法字符。
xml
<template>
<input
type="text"
@input="handleBasicInput"
:value="inputValue"
placeholder="请输入数字"
/>
</template>
<script>
export default {
data() {
return {
inputValue: ''
}
},
methods: {
handleBasicInput(e) {
// 正则替换:移除非数字字符
this.inputValue = e.target.value.replace(/\D/g, '');
// 同步更新DOM(防止光标跳转问题)
e.target.value = this.inputValue;
}
}
}
</script>
推荐方案 4: @blur
时格式化(兼容原有逻辑)
原理:在失焦时对值进行标准化处理。
javascript
methods: {
validateFixed(val, field) {
// 转换科学计数法为普通数字
let value = Number(val.target.value).toFixed(8);
// 处理 NaN 情况
if (isNaN(value)) value = 0;
// 更新数据
this.$set(this.formData.paymentRoutine, field, value);
}
}
推荐方案 5:自定义指令(推荐团队使用)
全局注册指令:
javascript
// main.js
Vue.directive('number-input', {
bind(el, binding, vnode) {
el.addEventListener('input', (e) => {
let value = e.target.value.replace(/[^\d.-]/g, '');
// 更多校验逻辑...
vnode.context[binding.expression] = Number(value);
});
}
});
模板中使用:
ini
<input
v-number-input
:value="formData.paymentRoutine.totalServiceFee"
type="text"
/>
为什么会出现科学计数法?
- 浏览器对
type="number"
的默认行为 - 当输入值
< 0.000001
或> 1e21
时自动转换 - 目的是节省显示空间(但严重影响表单体验)
方案建议
- 简单场景 :方案 2(
step
属性) - 需要严格控制格式 :方案 1(
type="text"
+ 正则) - 已有大量代码 :方案 4(
@blur
格式化) - 企业级项目:方案 5(自定义指令)