Vue3处理number输入框避免NaN
在 Vue3 中处理 number
类型输入框避免显示 NaN
,核心在于正确处理用户输入的非数字值。以下是几种解决方案:
方案1:使用字符串中转 + 计算属性(推荐)
vue
复制
下载
<template><input v-model="inputValue" type="text"@blur="handleBlur"placeholder="请输入数字"> </template><script setup> import { ref, computed } from 'vue'const numberValue = ref(0) // 存储实际数字值 const inputValue = computed({get: () => numberValue.value.toString(),set: (newValue) => {// 过滤非数字字符(保留负号和小数点)const filtered = newValue.replace(/[^0-9.-]/g, '')// 处理多个负号/小数点let cleanValue = filtered.replace(/(?!^)-/g, '') // 保留开头的负号.replace(/(\..*)\./g, '$1') // 保留第一个小数点// 更新输入框显示inputValue.value = cleanValue// 转换数字并更新存储值const num = parseFloat(cleanValue)if (!isNaN(num)) {numberValue.value = num}} })// 失焦时清理无效输入 const handleBlur = () => {if (inputValue.value === '-' || inputValue.value === '.') {inputValue.value = ''numberValue.value = 0} } </script>
方案2:使用自定义指令(输入过滤)
vue
复制
下载
<template><input v-model="numberValue" v-number-inputtype="text"> </template><script setup> import { ref } from 'vue'const numberValue = ref(0)// 自定义指令 const vNumberInput = {mounted(el) {el.addEventListener('input', (e) => {let value = e.target.value// 移除非数字字符(保留负号和小数点)value = value.replace(/[^\d.-]/g, '')// 处理多个负号/小数点value = value.replace(/(?!^)-/g, '').replace(/(\..*)\./g, '$1')e.target.value = value})} } </script>
方案3:使用 watch + 正则过滤(简单场景)
vue
复制
下载
<template><input v-model="inputValue" type="text"> </template><script setup> import { ref, watch } from 'vue'const inputValue = ref('') const numberValue = ref(0)watch(inputValue, (newVal) => {// 清理非法字符const cleanValue = newVal.replace(/[^\d.-]/g, '').replace(/(?!^)-/g, '').replace(/(\..*)\./g, '$1')// 更新显示值if (newVal !== cleanValue) {inputValue.value = cleanValue}// 转换数字const num = parseFloat(cleanValue)numberValue.value = isNaN(num) ? 0 : num }) </script>
关键处理点:
-
输入过滤:
-
使用正则
/[^\d.-]/g
移除非数字字符(保留负号和小数点) -
处理多个负号:
replace(/(?!^)-/g, '')
-
处理多个小数点:
replace(/(\..*)\./g, '$1')
-
-
NaN 处理:
-
使用
parseFloat()
转换 -
用
isNaN()
检测,无效时回退默认值(如 0)
-
-
边界情况:
-
单独负号/小数点时(
"-"
或"."
)在 blur 时清理 -
空字符串处理为 0
-
-
用户体验:
-
允许中间编辑(不强制即时转换)
-
失焦时做最终清理
-
为什么避免直接使用 type="number"
?
-
浏览器原生数字输入框:
-
仍可能提交空值/无效值
-
在不同浏览器表现不一致
-
无法完全控制显示内容
-
会显示原生增减按钮(可能不符合UI需求)
-
推荐使用 方案1(字符串中转 + 计算属性),它提供了最完整的控制逻辑,同时保持了 Vue 的响应式特性。