使用方法:v-number
//最大值最小值小數點位數
<el-input v-model.trim="scope.row.value"
v-number="{ min: 0 ,precision: 0,max: 999 }"
placeholder="非必填,0-999整數"
size="small"></el-input>
</el-form-item>
<el-input v-number="{min:0,max:100}"
step="1"
v-model="warnSampleRatio">
</el-input>
//不填
<el-input v-number="{}"
step="1"
v-model="warnSampleRatio">
</el-input>
自定義指令寫法:
/**
* 設置輸入框的值,觸發input事件,改變v-model綁定的值
* */
const setVal = (val, el, vNode) => {
if (vNode.componentInstance) {
// 如果是自定義組件就觸發自定義組件的input事件
vNode.componentInstance.$emit('input', val);
} else {
// 如果是原生組件就觸發原生組件的input事件
el.value = val;
el.dispatchEvent(new Event('input'));
}
};
/**
* 參數檢查
* */
const optionCheck = (binding) => {
// 範圍值是否爲數值
if ((binding.value.max && typeof binding.value.max !== 'number') || (binding.value.min && typeof binding.value.min !== 'number')) {
throw new Error('Range parameter must be numeric');
}
// 最大最小值存在的時候判斷最大值與最小值是否相等
if (binding.value.max === binding.value.min && typeof binding.value.max !== 'undefined' && typeof binding.value.min !== 'undefined') {
throw new Error('The maximum and minimum values cannot be equal');
}
};
/**
* 判斷是否爲無效值
* */
const isInvalidVal = (bindValue) => {
return bindValue === null || isNaN(Number(bindValue)) || bindValue.toString().indexOf('.') === bindValue.length - 1 || bindValue.toString().indexOf('e') !== -1;
};
/**
* 處理數值範圍,如果輸入值超過最大值或最小值,將會被自動設置爲邊界值
* */
const dealRange = (inputValue, binding) => {
let bindMax = typeof binding.value.max === 'undefined' ? Infinity : binding.value.max;
let bindMin = typeof binding.value.min === 'undefined' ? -Infinity : binding.value.min;
let result = inputValue;
if (inputValue < bindMin) {
result = bindMin;
}
if (inputValue > bindMax) {
result = bindMax;
}
return result;
};
/**
* 阻止輸入
* */
const preventInput = (event) => {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
};
export default {
bind(el, binding, vNode) {
optionCheck(binding);
// 處理無效值
let bindValue = vNode.data.model.value;
if (isInvalidVal(bindValue)) {
setVal(null, el, vNode);
return;
}
// 處理數值範圍
let inputVal = dealRange(bindValue, binding);
setVal(inputVal, el, vNode);
},
inserted(el, binding, vNode) {
let content;
// 按鍵按下=>只允許按照一定規則輸入 數字/小數點/減號
el.addEventListener('keypress', e => {
const inputKey = String.fromCharCode(typeof e.charCode === 'number' ? e.charCode : e.keyCode);
const inputReg = /\d|\.|-/;
content = e.target.value;
/**
* 1.輸入值不是數字、小數點、減號
* 2.輸入框爲空或只有減號,不能輸入小數點
* 3.重複輸入小數點
* 4.輸入框已有值,不能輸入減號
* 5.重複輸入減號
*/
// todo:已有值的時候,選中輸入框的所有值輸入減號‘-’,無法覆蓋輸入
if (!inputReg.test(inputKey)) {
preventInput(e);
} else if (((content === '' || content === '-') && inputKey === '.')) {
preventInput(e);
} else if ((content.indexOf('.') !== -1 && inputKey === '.')) {
preventInput(e);
} else if ((content !== '' && inputKey === '-')) {
preventInput(e);
} else if ((content.indexOf('-') !== -1 && inputKey === '-')) {
preventInput(e);
}
});
// 按鍵彈起=>並限制最大最小
el.addEventListener('keyup', e => {
if (e.keyCode === 8) {
return;
}
// 處理無效值
let bindValue = e.target.value;
if (bindValue === null) {
setVal(null, el, vNode);
return;
}
// 處理數值範圍
let inputVal = dealRange(bindValue, binding);
setVal(inputVal, el, vNode);
});
// 失去焦點=>保留指定位小數
el.addEventListener('focusout', e => { // 此處會在 el-input 的 @change 後執行
// 處理無效值
let bindValue = e.target.value;
if (isInvalidVal(bindValue)) {
setVal(null, el, vNode);
return;
}
content = parseFloat(e.target.value);
let contentStr = String(content);
if (contentStr.indexOf('.') >= 0 && contentStr.split('.')[1].length > binding.value.precision) {
let arg_precision = 0;// 默認保留至整數
if (binding.value.precision) {
arg_precision = parseFloat(binding.value.precision);
}
content = content.toFixed(arg_precision);
}
setVal(content, el, vNode);
});
}
};