步驟 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
。 處理后的值會覆蓋用戶輸入,確保始終符合規則。 支持輸入法組合輸入(如中文拼音),提升用戶體驗。