import type { App } from 'vue';
|
/**
|
* @fileoverview 输入限制
|
* 使用方法见 vue-input-directive{@link https://github.com/MaiYaoqiang/vue-input-directive}
|
* @author wujingjing <gersonwu@qq.com>
|
*/
|
|
const trigger = (el, type) => {
|
const e = document.createEvent('HTMLEvents');
|
e.initEvent(type, true, true);
|
el.dispatchEvent(e);
|
};
|
const compositionstart = (e) => {
|
e.target.composing = true;
|
};
|
const compositionend = (e) => {
|
e.target.composing = false;
|
trigger(e.target, 'input');
|
};
|
let initId = 0;
|
// 生成绑定方法
|
const getBindFun = function (handler) {
|
const id = initId++;
|
const bindFun = (el, binding) => {
|
const ele = el.tagName === 'INPUT' ? el : el.querySelector('input');
|
// 把一些信息存起来 用于判断是否需要重新绑定事件
|
// 因为每次输入的时候都会触发指令的update 重复绑定没意义
|
if (!ele[id]) {
|
ele[id] = {
|
oldCallback: null,
|
oldValue: null,
|
};
|
}
|
const oldData = ele[id];
|
const value = (binding.value && binding.value.toString()) || undefined;
|
if (oldData.oldValue !== value) {
|
oldData.oldValue = value;
|
if (oldData.oldCallback) {
|
ele.removeEventListener('keyup', oldData.oldCallback);
|
ele.removeEventListener('blur', oldData.oldCallback);
|
ele.removeEventListener('compositionstart', compositionstart);
|
ele.removeEventListener('compositionend', compositionend);
|
}
|
const callback = (e) => {
|
if (!e.target.composing) {
|
handler(ele, binding);
|
// 不加Trigger会导致输入完 blur后数据变化
|
trigger(ele, 'input');
|
}
|
};
|
ele.addEventListener('keyup', callback);
|
ele.addEventListener('blur', callback);
|
ele.addEventListener('compositionstart', compositionstart);
|
ele.addEventListener('compositionend', compositionend);
|
oldData.oldCallback = callback;
|
}
|
};
|
return bindFun;
|
};
|
// 生成对应指令需要的生命周期的列表
|
const getBindListFun = function (bindFun) {
|
return {
|
mounted: bindFun,
|
updated: bindFun,
|
inserted: bindFun,
|
update: bindFun,
|
};
|
};
|
// 生成指令对象方法
|
const DInitFun = function (handler) {
|
const bindFun = getBindFun(handler);
|
return getBindListFun(bindFun);
|
};
|
|
// 输入数字限制最大值
|
/**
|
* @example
|
<el-input
|
v-d-input-max="99.99"
|
v-model="value"></el-input>
|
*/
|
const DInputMax = (ele, binding) => {
|
let value = ele.value + '';
|
if (parseFloat(value) > parseFloat(binding.value)) {
|
value = binding.value;
|
}
|
ele.value = value;
|
};
|
|
// 输入数字限制最小值
|
/**
|
* @example
|
<el-input
|
v-d-input-min="99.99"
|
v-model="value"></el-input>
|
*/
|
const DInputMin = (ele, binding) => {
|
let value = ele.value + '';
|
if (parseFloat(value) < parseFloat(binding.value)) {
|
value = binding.value;
|
}
|
ele.value = value;
|
};
|
|
/**
|
* @example
|
<el-input
|
v-d-input-int
|
v-d-input-max="9999"
|
v-model="value"></el-input>
|
*/
|
// 只能输入正整数
|
const DInputInt = (ele, binding) => {
|
let value = ele.value + '';
|
const reg = /[1-9]{1}\d*/;
|
const matchRes = value.match(reg);
|
if (matchRes) {
|
value = matchRes[0];
|
} else {
|
value = '';
|
}
|
ele.value = value;
|
};
|
|
/**
|
* 精确到指定位数小数
|
* @example
|
<el-input
|
v-d-input-point
|
v-d-input-max="99.99"
|
v-model="value"></el-input>
|
*/
|
const DInputPoint = (ele, binding) => {
|
// 精确到几位小数,默认是 2 位
|
const decimalPrecision = binding.value ?? 2;
|
let value = ele.value + '';
|
|
const reg = new RegExp(`^(([1-9][0-9]*)|(([0].d{1,${decimalPrecision}}|[1-9][0-9]*.d{1,${decimalPrecision}})))$`);
|
const regSome = new RegExp(`[0-9]+.?[0-9]{0,${decimalPrecision}}`);
|
const matchRes = value.match(reg);
|
if (matchRes) {
|
// 符合 不需要做删减操作
|
} else {
|
// 若不符合 看是否符合部分
|
const matchResSome = value.match(regSome);
|
if (matchResSome) {
|
value = matchResSome[0];
|
} else {
|
value = '';
|
}
|
}
|
ele.value = value;
|
};
|
|
// 只能输入英文 大小写
|
const DInputEn = (ele, binding) => {
|
let value = ele.value + '';
|
const reg = /[a-zA-Z]*/;
|
const matchRes = value.match(reg);
|
if (matchRes) {
|
value = matchRes[0];
|
} else {
|
value = '';
|
}
|
ele.value = value;
|
};
|
|
/**
|
* @example
|
<el-input
|
v-d-input-regexp="/[0-9]{0,18}/"
|
v-model="value"></el-input>
|
*/
|
// 限制不能输入中文v-d-input-regexp="/((?![\u4E00-\u9FA5]).)*/"
|
// 仅可输入数字字母v-d-input-regexp="/[0-9A-Za-z]*/"
|
const DInputRegexp = (ele, binding) => {
|
let value = ele.value + '';
|
const reg = binding.value;
|
const matchRes = value.match(reg);
|
if (matchRes) {
|
value = matchRes[0];
|
} else {
|
value = '';
|
}
|
ele.value = value;
|
};
|
|
const inputMax = DInitFun(DInputMax);
|
const inputMin = DInitFun(DInputMin);
|
const inputInt = DInitFun(DInputInt);
|
const inputPoint = DInitFun(DInputPoint);
|
const inputEn = DInitFun(DInputEn);
|
const inputRegexp = DInitFun(DInputRegexp);
|
export const inputLimit = (app: App) => {
|
app.directive('d-input-max', inputMax);
|
app.directive('d-input-min', inputMin);
|
app.directive('d-input-int', inputInt);
|
app.directive('d-input-point', inputPoint);
|
app.directive('d-input-en', inputEn);
|
app.directive('d-input-regexp', inputRegexp);
|
};
|