1. 安装和引入
首先,将这个自定义指令代码保存到一个文件,例如
v-input.js
。然后在你的 Vue 项目中引入和注册这个自定义指令。
// main.js 或其他入口文件
import Vue from 'vue';
import VInput from './path/to/v-input';
Vue.directive('input', VInput);
2. 使用自定义指令
在你的 Vue 组件中,你可以使用这个自定义指令来控制输入框的行为。以下是如何在模板中使用这个指令的详细说明。
基本用法
你可以在模板中使用
v-input
指令来绑定各种输入限制类型。例如:
<template>
<div>
<!-- 只允许输入数字 -->
<input v-input.num />
<!-- 只允许输入浮点数 -->
<input v-input.float="2" />
<!-- 只允许输入正整数 -->
<input v-input.intp />
<!-- 只允许输入字母 -->
<input v-input.alp />
<!-- 只允许输入数字和字母 -->
<input v-input.num_alp />
<!-- 只允许输入四则运算符和数字 -->
<input v-input.arith />
<!-- 只允许输入在 10 到 100 范围内的整数 -->
<input v-input.intRange="10-100" />
<!-- 只允许输入双精度浮点数,在 1.0 到 100.0 范围内 -->
<input v-input.double="1.0-100.0" />
</div>
</template>
指令参数说明
num
: 只允许输入数字。num_point
: 只允许输入数字和小数点。float
: 只允许输入浮点数。binding.value
可以指定小数点后的位数(例如"2"
表示保留两位小数)。int
: 只允许输入整数(去掉开头的多个0)。intp
: 只允许输入正整数(去掉开头的0)。alp
: 只允许输入字母。num_alp
: 只允许输入数字和字母。arith
: 只允许输入算术运算符(+ - * /)和数字。intRange
: 只允许输入指定范围内的整数。例如"10-100"
表示范围从 10 到 100。double
: 只允许输入指定范围内的双精度浮点数。例如"1.0-100.0"
表示范围从 1.0 到 100.0。
3. 注意事项
- 中文输入: 在使用中文输入法时,输入的处理可能会因为
compositionstart
和compositionend
事件而被锁定。确保在输入完成后,能够正确更新绑定的数据。 - 输入格式: 这个自定义指令处理了多种输入类型,确保你根据实际需求选择合适的指令参数。
4. 调试和测试
在使用自定义指令时,建议对不同类型的输入进行充分测试,以确保其行为符合预期。特别是针对边界条件和特殊字符的输入,进行详细的测试可以帮助确保输入验证的准确性。
完整示例
以下是一个完整的 Vue 组件示例,展示了如何使用自定义指令:
<template>
<div>
<h3>请输入不同类型的数据:</h3>
<input v-input.num placeholder="数字" />
<input v-input.float="2" placeholder="浮点数(2位小数)" />
<input v-input.intp placeholder="正整数" />
<input v-input.alp placeholder="字母" />
<input v-input.num_alp placeholder="数字和字母" />
<input v-input.arith placeholder="四则运算符和数字" />
<input v-input.intRange="10-100" placeholder="范围内整数(10到100)" />
<input v-input.double="1.0-100.0" placeholder="范围内浮点数(1.0到100.0)" />
</div>
</template>
<script>
import VInput from './path/to/v-input';
export default {
directives: {
input: VInput
}
};
</script>
<style>
/* 这里可以添加一些样式 */
</style>
5.具体指令代码
export default {
bind(el, binding, vnode) {
// 查找输入元素(支持 input 和 textarea)
const input =
el.querySelector(".el-input__inner") ||
el.querySelector(".el-textarea__inner") ||
el;
// 处理中文输入法的 compositionstart 和 compositionend 事件
input.addEventListener("compositionstart", () => {
vnode.locking = true; // 锁定输入,避免中文输入导致双向绑定失效
});
input.addEventListener("compositionend", () => {
vnode.locking = false; // 解除锁定
input.dispatchEvent(new Event("input")); // 触发 input 事件,以更新数据
});
// 处理键盘输入事件
input.onkeyup = () => {
let newModifiers = vnode.key; // 获取指令参数(例如 'num' 或 'intp')
let newRules;
// 如果指令参数包含 ':'
if (newModifiers && newModifiers.includes(":")) {
let info = newModifiers.split(":");
newModifiers = info[0]; // 指令类型(例如 'intRange')
newRules = info[1]?.split("-"); // 规则(例如范围 [0-100])
}
if (vnode.locking) {
return; // 如果输入被锁定,则不处理
}
// 根据指令参数选择不同的输入处理函数
switch (newModifiers) {
case "double":
onlyDouble(input, newRules); // 处理双精度浮点数
break;
case "intRange":
onlyIntRange(input, newRules); // 处理整数范围
break;
case "num":
onlyNum(input); // 处理数字
break;
case "num_point":
onlyNumPoint(input); // 处理数字和小数点
break;
case "float":
onlyFloat(input, binding.value); // 处理浮点数(限制小数位数)
break;
case "int":
onlyInt(input); // 处理整数(无前导零)
break;
case "intp":
onlyIntp(input); // 处理正整数
break;
case "alp":
onlyAlp(input); // 处理字母
break;
case "num_alp":
onlyNumAlp(input); // 处理数字和字母
break;
case "arith":
onlyArith(input); // 处理算术运算符和数字
break;
default:
break;
}
input.dispatchEvent(new Event("input")); // 触发 input 事件,以更新数据
};
// 处理双精度浮点数输入
function onlyDouble(input, rules) {
onlyFloat(input, 1); // 先确保输入符合浮点数格式
if (input.value < Number(rules[0])) {
input.value = Number(rules[0]); // 处理范围下限
} else if (input.value > Number(rules[1])) {
input.value = Number(rules[1]); // 处理范围上限
}
}
// 处理整数范围输入
function onlyIntRange(input, rules) {
onlyIntp(input); // 处理正整数输入
if (input.value < Number(rules[0])) {
input.value = Number(rules[0]); // 处理范围下限
} else if (input.value > Number(rules[1])) {
input.value = Number(rules[1]); // 处理范围上限
}
}
// 处理仅数字输入
function onlyNum(input) {
input.value = input.value.replace(/\D+/g, ""); // 去掉非数字字符
}
// 处理整数输入(无前导零)
function onlyInt(input) {
let value = input.value.replace(/\D+/g, ""); // 去掉非数字字符
input.value = value ? Number(value).toString() : value; // 去掉开头多个0
}
// 处理正整数输入(去掉前导零)
function onlyIntp(input) {
const value = input.value.replace(/\D+/g, ""); // 去掉非数字字符
input.value = /^[1-9][0-9]*$/.test(value) ? value : value.replace(/^0+/, ""); // 确保为正整数,去掉前导零
}
// 处理数字和小数点输入
function onlyNumPoint(input) {
input.value = input.value.replace(/[^\d.]/g, ""); // 允许数字和小数点
}
// 处理浮点数输入(限制小数位数)
function onlyFloat(input, n) {
let value = input.value;
value = value.replace(/[^\d.]/g, ""); // 允许数字和小数点
value = value.replace(/^\./g, ""); // 去掉开头的点
value = value.replace(".", "$#$").replace(/\./g, "").replace("$#$", "."); // 处理多个点的情况
if (n && Number(n) > 0) {
const d = new Array(Number(n)).fill("\\d").join(""); // 构建正则表达式
const reg = new RegExp(`^(\\-)*(\\d+)\\.(${d}).*$`, "ig");
value = value.replace(reg, "$1$2.$3"); // 限制小数位数
}
if (value && !value.includes(".")) {
value = Number(value).toString(); // 去掉开头多个0
}
input.value = value;
}
// 处理字母输入
function onlyAlp(input) {
input.value = input.value.replace(/[^A-Za-z]/g, ""); // 只允许字母
}
// 处理数字和字母输入
function onlyNumAlp(input) {
input.value = input.value.replace(/[^A-Za-z0-9]/g, ""); // 只允许数字和字母
}
// 处理算术运算符和数字输入
function onlyArith(input) {
let value = input.value;
if (value) {
input.value = value.split("").reduce((prev, cur) => {
if (/^[\d|\-|\+|\*|\/|\.|\(|\)]+$/.test(cur)) {
return prev + cur; // 只允许数字和算术运算符
}
return prev;
}, "");
}
}
},
};
版权归原作者 码农六六 所有, 如有侵权,请联系我们删除。