一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
最近项目有一个表达式校验的需求,特意记录下来学习探讨,以下是简化后的小案例,只进行了简单实现,如果有问题,欢迎大家指正!
功能简介
(1)该案例包括条件列表、逻辑运算符(并且、或者、非)、小括号、表达式输入框、校验按钮。
(2)条件列表展示需要进行运算的条件信息,点击一行,向表达式中指定光标后添加条件编号;点击逻辑运算符按钮,向表达式中指定光标后添加该逻辑运算符;点击校验按钮,校验表达式是否合法,并给出提示。
演示结果
整体效果
校验结果
还有很多种情况的提示,就不一一列举啦
思考
1、括号是否匹配,是否存在空括号;
2、逻辑运算符的使用是否合法,这个情况比较多,比如并且运算符需要连接两个条件、运算符不能连续、非运算符前需要有条件等,把所有不合法的情况列举出来,并给出相应的提示。
代码实现
校验模块
checkExpression(string) {
let msg = "校验通过";
// 剔除空白符
string = string.replace(/\s/g, "");
// 错误情况,空字符串
if (string === "") {
msg = "请输入条件表达式";
return msg;
}
// 错误情况,括号不配对
const stack = [];
for (let i = 0, item; i < string.length; i++) {
item = string.charAt(i);
if ("(" === item) {
stack.push("(");
} else if (")" === item) {
if (stack.length > 0) {
stack.pop();
} else {
stack.push(")");
}
}
}
if (stack.length !== 0) {
msg = "括号不匹配";
return msg;
}
// 空括号
if (/\(\)/.test(string)) {
msg = "存在空括号";
return msg;
}
//错误情况,并且,或者不能在首位,且不能存在 \( (并且|或者) (并且|或者)\)
const matchResult = string.match(/^(并且|或者)|(\((并且|或者))|((并且|或者)\))/g);
if (matchResult) {
msg =
"条件运算符【" +
(matchResult[0].includes("并且") ? "并且" : "或者") +
"】只能用来连接两个完整的条件";
return msg;
}
// 错误情况,运算符连续
if (/(并且|或者){2,}/.test(string)) {
msg = "运算符连续";
return msg;
}
// 错误情况,非运算符前不能跟 ) 和条件
if (/[\\)]非/.test(string)) {
msg = "非运算符前需要有条件运算符";
return msg;
}
// 错误情况,非运算符后不能跟 ) 并且, 或者
if (new RegExp("非(\\)|并且|或者)").test(string)) {
msg = "非运算符后需要紧跟条件";
return msg;
}
// 错误情况,不能以运算符结尾
if (/(并且|或者|非)$/.test(string)) {
msg = "条件表达式不完整";
return msg;
}
// 错误情况,(后面是运算符
if (/\(["并且","或者"]/.test(string)) {
return msg;
}
// 错误情况,)前面是运算符
if (/["并且","或者"]\)/.test(string)) {
return msg;
}
return msg;
},
向当前光标位置后添加字符串
insertNode(str) {
const tc = document.getElementById("expression-input");
const tclen = tc.value.length;
tc.focus();
let startlength = 0;
if (tc.selectionStart || tc.selectionStart == "0") {
//IE11
//火狐和谷歌
startlength = tc.selectionStart + str.length;
tc.value =
tc.value.substr(0, tc.selectionStart) + str + tc.value.substring(tc.selectionEnd, tclen);
this.operationExpression = tc.value;
//设置光标位置,火狐和谷歌
tc.selectionStart = startlength;
tc.selectionEnd = startlength;
} else {
tc.value += str;
this.operationExpression = tc.value;
tc.focus();
}
}
总结
1、该功能主要是使用正则来实现的,正则的使用确实方便了很多功能的实现,通过这个小案例也算是对正则的复习。
2、考虑不合法情况的,对于提升思考问题的能力还是很有帮助的,我的能力一般,再接再厉吧。
3、向当前光标位置后添加字符串功能并不完善,有待优化。