Vue和Element-UI这两大框架在前端开发中应用已经非常nice了。但是在开发中还是有很多不足之处。以大量的使用基础,来不断的改进吧。
常规Element的表单验证
偷个懒,这里首先去官网看看表单验证的基本用法
https://element.eleme.cn/#/zh-CN/component/form
关键代码
<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="密码" prop="pass">
<el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" v-model="ruleForm.checkPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model.number="ruleForm.age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
<script>
export default {
data() {
var checkAge = (rule, value, callback) => {
if (!value) {
return callback(new Error('年龄不能为空'));
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
if (value < 18) {
callback(new Error('必须年满18岁'));
} else {
callback();
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.ruleForm.checkPass !== '') {
this.$refs.ruleForm.validateField('checkPass');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.ruleForm.pass) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
ruleForm: {
pass: '',
checkPass: '',
age: ''
},
rules: {
pass: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
],
age: [
{ validator: checkAge, trigger: 'blur' }
]
}
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
核心代码
rules: {
pass: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
],
age: [
{ validator: checkAge, trigger: 'blur' }
]
}
这段代码可以完成密码一致性的实时校验、但是在线上需求中,不仅要校验一致性、还要通过正则校验密码文本的字符等
优化成js工具类引用即可注入校验规则
JS代码
let passwordValid = [
{required: true, message: '请输入密码', trigger: ['change', 'blur']},
{pattern: /^[a-zA-Z0-9_@$^!~,.*]{4,20}$/, message: '密码仅允许数字、字母、下划线、特殊字符,4到20位', trigger: ['change', 'blur']},
]
let equalsCache = {}
let validEquals = (rule, value, callback) => {
let key = rule.meta.groupId + '-' + (rule.meta.tag === true)
let otherKey = rule.meta.groupId + '-' + (rule.meta.tag === false)
equalsCache[key] = value
if (rule.meta.tag === true && equalsCache[otherKey]) {
if (equalsCache[otherKey] !== equalsCache[key]) {
callback(new Error(rule.message));
return
}
}
callback()
};
let textEqualsValid = (groupId, tag, message) => {
return [{validator: validEquals, trigger: 'blur', message: message, meta: {groupId: groupId, tag: tag}}]
}
export const CommValidation = {
/**
* 密码格式验证
*/
passwordValid: passwordValid,
/**
* 文本一致性验证
*/
textEqualsValid: textEqualsValid,
}
这个js工具类提供两个功能、一个是密码格式验证,一个是两个文本框是否一致
这里有个比较难处理的问题,每个单独的表单项验证体系中,不会存储另一个表单项的值,所以我采用了equalsCache 表
来共享数据,一方面解耦了vue的依赖,另一方面由于cache会存放表单明文值,如果不清理可能造成安全隐患,这里本质上不好清理,因为js类中没有很好的理由提供回调,这样代码就太丑了。因为我们可以通过数据签名来验证数据的一致性,从而保证了明文数据不被保存。
关于上述的问题为何我要纠结明文数据在web页面"存储"的安全性
,从概率来讲,将明文数据缓存在浏览器内存的命中概率不高,第一:页面的生命周期不长、第二:此操作的频繁性低。但是这样的操作依然是安全隐患。这相关Web页面的计算机安全问题,暂时不讨论太多,我们作为开发只要保证,尽可能减少敏感数据的传输、存储即可
,这里的存储应该是广义的,即信息被某种载体记录。此载体可以是硬盘、文件、内存、大脑、等等。在传输信号时载体的记录形式在发生跃迁,这此跃迁过程中,信号随时可能被窃取并以不为人知的方式存储了下来。
代码简化
rules: {
pass:CommValidation.passwordValid.concat(CommValidation.textEqualsValid('InfoPwd',false,'两次密码不一致!')),
checkPass: CommValidation.passwordValid.concat(CommValidation.textEqualsValid('InfoPwd',true,'两次密码不一致!')),
age: [
{ validator: checkAge, trigger: 'blur' }
]
}
最后谈谈这个js放哪里
写代码最头疼的两问,这段代码叫啥名字、这段代码放哪里
。关于命名、项目结构也就不多谈了,这玩意太复杂,我也不太懂,我只知道一切需要规范、规约、原则、这样才能得心应手的搬砖。
作为验证工具类,
-
与项目相关性不大的验证策略:身份证、手机号、出生日期等这些比较固定的验证策略,这种我们应该放在与项目同级的工具包中,即这些代码也可以提供给其他项目使用。当然手机号这玩意的验证也是特复杂。
-
验证策略与项目相关的。比如密码验证、用户名验证、等等。这种由于和项目耦合我们应该放在项目的validation文件夹中。