实现了整数位数、小数位数、是否可录入负数、小数位是否自动补0的控制。太好用了!!!
// numlength.js
/**
* 触发事件
* @param {string} name 事件名
*/
function event(name) {
var evt = document.createEvent('Event')
evt.initEvent(name, true, true)
return evt
}
/**
* 修改光标位置
* @param {*} el
* @param {*} position
*/
function setCursor(el, position) {
var setSelectionRange = function() { el.setSelectionRange(position, position) }
if (el === document.activeElement) {
setSelectionRange()
setTimeout(setSelectionRange, 1) // Android Fix
}
}
/**
* 格式化value
* @param {*} fv 最初的value
* @param {string} intlen 整数长度
* @param {string} deciLen 小数长度
* @param {boolean} negative 修饰符标识
* @param {boolean} short 修饰符标识
* @param {boolean} b blur失去焦点时的格式化标识
*/
function formatVal(fv, intlen, deciLen, negative, short, b) {
// console.log(negative)
let value = fv
let lose = ''
if (fv.indexOf('-') > -1) { lose = '-' }
if (fv.indexOf('+') > -1) { lose = '' }
const v = fv.replace(/[^\d\.]/g, '')
const vArr = v.split('.')
vArr.length = vArr.length > 2 ? 2 : vArr.length
if (intlen || intlen === '0') {
vArr[0] = vArr[0].slice(0, intlen)// 裁剪 整数部分
}
if (b && !vArr[0]) { // 失去焦点后 整数部分为空, 默认给整数0
vArr[0] = '0'
}
if (deciLen && vArr[1]) {
vArr[1] = vArr[1].slice(0, deciLen)// 裁剪 小数部分
} else if ((b || deciLen === '0') && !vArr[1]) {
vArr.length = 1
}
if (!negative) { lose = '' }// 默认正数
const strNum = vArr.join('.')
if (b && !strNum) {
value = ''
} else {
value = lose + strNum
}
if (b && value) {
value = parseFloat(value).toFixed(deciLen)
if (short && /\.\d/.test(value)) {
value = parseFloat(value).toString()
}
}
return value
}
/**
* input 限制数字长度
* @author shv
*
* 使用方式: el-input 或 input 添加指令
* v-money:9_2.negative
* 说明:
* :9_2 : 指令参数 9:整数的位数,取值范围[1-9];2:小数的位数,取值范围[0-9]
* .negative : 指令修饰符 允许输入负数,否则默认整数(含小数)
* .canempty : 指令修饰符 可以为空 加上后为空字符串时不格式化为0
* .short : 指令修饰符 小数位不补零
* 特殊使用形式:
* 1 v-money 整数长度默认9 小数长度默认2 只能是正数
* 2 v-money.negative 整数长度默认9 小数长度默认2 允许输入负数
* 3 v-money:5_2 整数长度5 小数长度2 只能是正数
*
*/
export default {
bind: (el, binding, vnode) => {
let inputEl = null
let intlen = '9' // 整数长度默认值(亿级别)
let deciLen = '2' // 小数长度默认值
if (el.tagName === 'INPUT') {
inputEl = el // 支持el-input
} else {
inputEl = el.getElementsByTagName('input')[0] // 支持原生input
}
if (inputEl) {
const arg = (binding.arg || '').split('_')
const modifiers = binding.modifiers
intlen = arg[0] || intlen
deciLen = arg[1] || deciLen
let flag = true
inputEl.addEventListener('compositionstart', () => {
flag = false
})
inputEl.addEventListener('compositionend', () => {
flag = true
inputEl.dispatchEvent(event('input'))
})
inputEl.oninput = (e, b) => {
if (flag) {
var positionFromEnd = inputEl.value.length - inputEl.selectionEnd
const fv = e.target.value || '' // 原始value
if (fv === '' && modifiers.canempty) {
return
}
const lv = formatVal(fv, intlen, deciLen, modifiers.negative, modifiers.short, b) // 最终 value
if (lv !== fv) { // 防死循环
e.target.value = lv
positionFromEnd = lv.length - positionFromEnd
setCursor(inputEl, positionFromEnd)
inputEl.dispatchEvent(event('input'))
// inputEl.dispatchEvent(event('change'))
}
}
}
inputEl.onblur = (e) => {
inputEl.oninput(e, true)
// inputEl.dispatchEvent(event('input'))
}
}
}
}
// main.js
Vue.directive('money', numlength)