步骤 1:创建自定义指令
function processValue(value) {let filtered = value.replace(/[^\d.]/g, '');const firstDotIndex = filtered.indexOf('.');if (firstDotIndex !== -1) {filtered = filtered.substring(0, firstDotIndex + 1) + filtered.substring(firstDotIndex + 1).replace(/\./g, '');}const parts = filtered.split('.');let integerPart = (parts[0] || '').slice(0, 10); let decimalPart = parts.length > 1 ? parts[1].slice(0, 2) : ''; if (filtered.startsWith('.') && integerPart === '') {integerPart = '0';}let newValue = integerPart;if (parts.length > 1 || filtered.endsWith('.')) {newValue += '.' + decimalPart;}return newValue;
}
Vue.directive('number', {bind(el, binding, vnode) {const input = el.querySelector('input.el-input__inner');if (!input) return;let composing = false; const handler = (e) => {if (composing) return;const newVal = processValue(e.target.value);if (e.target.value !== newVal) {e.target.value = newVal;input.dispatchEvent(new Event('input', { bubbles: true })); }};const compositionStart = () => { composing = true; };const compositionEnd = (e) => {composing = false;handler(e);};input.addEventListener('compositionstart', compositionStart);input.addEventListener('compositionend', compositionEnd);input.addEventListener('input', handler);el._numberHandlers = { compositionStart, compositionEnd, handler };const initialValue = vnode.componentInstance?.value ?? input.value;const processedVal = processValue(initialValue);if (initialValue !== processedVal) {vnode.componentInstance?.$emit('input', processedVal);}},update(el, binding, vnode) {const input = el.querySelector('input.el-input__inner');const currentValue = vnode.componentInstance?.value ?? input?.value;if (currentValue === undefined) return;const newVal = processValue(currentValue);if (currentValue !== newVal) {vnode.componentInstance?.$emit('input', newVal);}},unbind(el) {const input = el.querySelector('input.el-input__inner');if (input && el._numberHandlers) {const { compositionStart, compositionEnd, handler } = el._numberHandlers;input.removeEventListener('compositionstart', compositionStart);input.removeEventListener('compositionend', compositionEnd);input.removeEventListener('input', handler);delete el._numberHandlers;}}
});
步骤 2:在组件中使用指令
<template><el-input v-number v-model="inputValue"></el-input>
</template><script>
export default {data() {return {inputValue: ''};}
};
</script>
功能说明
- 过滤非数字字符:只允许输入数字和小数点。
- 限制小数点数量:确保只保留第一个小数点,后续的自动移除。
- 整数部分限制:最多输入 10 位整数,超长部分截断。
- 小数部分限制:最多输入 2 位小数,超长部分截断。
- 输入法兼容:处理中文输入法状态,避免中途过滤。
- 初始值处理:当初始值不符合规则时自动修正。
- 实时更新:通过触发
input
事件确保 v-model
同步更新。
注意事项
- 该指令依赖于 Element UI 的
el-input
结构,确保内部输入框的类名为 el-input__inner
。 - 处理后的值会覆盖用户输入,确保始终符合规则。
- 支持输入法组合输入(如中文拼音),提升用户体验。