首先说明输入框中的格式限制如下:
(1)当第一位为0时,第二位只能输入小数点,且不能输入其他数字(如00)
(2)当第一位不为0时,后边不限制
(3)数据中只能输入一个小数点
(4)小数点后边保留2位
方案一:当输入后,在输入框中显示,然后检验输入内容,去掉不符合规则的数据;
优点:实现方式比较简单,通用于大多数平台(web端、移动端)
缺点:输入框中会显示一下历史不符合规则的输入的数据,然后消失
不说废话,直接上代码:
<input type="text" v-model="inputValue" @input="handleInput" />
const inputValue = ref('')
/**
* 功能: 数据格式校验【保留2位小数】
* e: input返回的值
*/
const handleInput = (e: any) => {
// 一定要加nextTick,否则特殊情况的更改不生效【如:000时,更改为0】
nextTick(() => {
let value = e.detail.value
// 如果当前输入为空,直接允许清空
if (!value) {
inputValue.value = ''
} else if (value?.charAt(0) === '0' && value.charAt(1) && value.charAt(1) !== '.') {
// // 1. 当第一位为0时,只能输入小数点【第二位必须是小数点】
value = '0'
}
value = value.replace(/[^\d.]/g, '') // 清除"数字"和"."以外的字符
value = value.replace(/\.{2,}/g, '.') // 只保留第一个. 清除多余的
value = value.match(/^\d*(\.?\d{0,2})/g)[0] || '' // 保留2位小数
inputValue.value = value
})
}
注意在handleInput方法中,一定要使用nextTick,否则部分赋值无效
方案二:使用自定义指令限制输入框的内容,不符合条件的,无法输入
优势:用户体验更好,使用更方便
缺点:由于uni-app对input做了一些包装,故该实现方法需要根据实际情况进行修改
(1)自定义指令
import type { Directive, App } from 'vue'
/**
* 输入框文本输入限制
*/
export const keepTwoDecimal: Directive = {
mounted(el, binding) {
el.addEventListener(
'input',
(e: any) => {
try {
let value = e.target.value
// 1. 当第一位为0时,只能输入小数点【第二位必须是小数点】
if (value.charAt(0) === '0' && value.length > 1 && value.charAt(1) !== '.') {
value = '0'
} else if(value.length === 1 && value.charAt(0) === '.') {
// 如果第一位输入的是小数点,则直接置空
value = ''
} else {
// 当input的type不为text时,输入小数时,光标会前移,此处需要手动将光标后移(虽然此处的代码抛出了异常,但是解决了光标前移的问题)
// if (e.data === '.') {
// e.target.selectionStart = value.length + 1
// e.target.selectionEnd = value.length + 1
// }
value = value.replace(/[^\d.]/g, '') // 清除"数字"和"."以外的字符
value = value.replace(/\.{2,}/g, '.') // 只保留第一个. 清除多余的
value = value.match(/^\d*(\.?\d{0,2})/g)![0] || '' // 保留2位小数
}
e.target.value = value
} catch (e) {
throw new Error('输入时发生异常!')
}
},
true,
) // 由于uni-app中渲染原生的input时,增加了dom解构,此处无法直接获取input标签的输入事件,故设置为true,添加向下捕获事件
},
}
export function setupInputDirective(app: App) {
app.directive('input-decimal', keepTwoDecimal)
}
(2)使用方法
<input class="input" type="text" v-input-decimal inputmode="numeric" v-model="inputValue" placeholder="请输入" />
注意:
(1)在自定义指令中,addEventListener的监听方法中要添加向下的捕获事件(因为uni-app将input包括了多层),即在其后边多传一个参数true,表示向下捕获.
(2)在使用时,直接使用“v-input-decimal”指令即可;
(3)如果在输入时,想直接调起数字键盘,需要添加inputmode="numeric"属性;
(4)如果type不等于text时,输入小数点时,光标会前移,为了解决此问题,需要在自定义指令中添加额外的判断(自定义的代码中已添加注释说明)
以上思路为自己在工作中的经验总结,如有问题,欢迎大家留言讨论!
本问为作者原创,如有需要,请注明出处,尊重原创,十分感谢!