步骤 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
。 处理后的值会覆盖用户输入,确保始终符合规则。 支持输入法组合输入(如中文拼音),提升用户体验。