在使用表单提交数据时,表单校验可对输入数据进行验证,保证输入数据的格式正确。
表单校验
<template>
<div class="container">
<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>
<password-line :passwordVal="ruleForm.pass"></password-line>
</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>
<el-button type="primary" @click="submitForm('ruleForm')"
>提交</el-button
>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import PasswordLine from "./PasswordLine"; // 引入密码复杂度校验组件
export default {
components: {
PasswordLine,
},
data() {
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: "",
},
rules: {
pass: [{ validator: validatePass, trigger: ["blur", "change"] }],
checkPass: [{ validator: validatePass2, trigger: ["blur", "change"] }],
},
};
},
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>
<style scoped>
.container {
padding-right: 100px !important;
padding: 30px;
width: 400px;
height: 200px;
border: 2px dashed skyblue;
}
</style>
密码复杂度校验组件
PasswordLine.vue
<template>
<div class="line-container" v-show="showProgress">
<div
class="line"
:style="{ width: `${progressPercent}%`, background: bgColor }"
></div>
<div class="tipWord" :style="{ color: bgColor }">
{{ tipWord }}
</div>
</div>
</template>
<script>
export default {
name: "PasswordLine",
props: {
passwordVal: {
type: String,
default: "",
},
},
data() {
return {
bgColor: "",
tipWord: "",
};
},
watch: {
progressPercent(v) {
if (v === 95) {
this.bgColor = "#64BC38";
this.tipWord = "Complex";
} else if (v === 50) {
this.bgColor = "#FAAD14";
this.tipWord = "Medium";
} else {
this.bgColor = "#F56C6C";
this.tipWord = "Simple";
}
},
},
computed: {
showProgress() {
return this.passwordVal.length >= 8;
},
progressPercent() {
if (!this.passwordVal) return 0;
// n:数字 l:小写字母 u:大写字母 s:特殊字符
const result = this.passwordVal
.split("")
.map((val) => val.charCodeAt())
.reduce(
(pre, val, index) => {
if (val < 48) pre.special += 1;
else if (val < 58) pre.num += 1;
else if (val < 65) pre.special += 1;
else if (val < 91) pre.upper += 1;
else if (val < 97) pre.special += 1;
else if (val < 123) pre.lower += 1;
else pre.special += 1;
return pre;
},
{ num: 0, lower: 0, upper: 0, special: 0 }
);
const arr = Object.values(result);
const len = this.passwordVal.length;
const zCount = this.zeroCount(arr)["0"];
if (len >= 8) {
if (!zCount) {
return 95;
} else if (zCount === 1 || zCount === 2) {
return 50;
} else {
return 28;
}
}
},
},
methods: {
zeroCount(arr) {
return arr.reduce((prev, next) => {
prev[next] = prev[next] + 1 || 1;
return prev;
}, {});
},
},
};
</script>
<style scoped>
.line-container {
position: relative;
top: -10px;
}
.line-container,
.line {
background: #d9dae0;
height: 8px;
border-radius: 4px 5px 5px 4px;
}
.tipWord {
position: absolute;
left: 0;
top: -2px;
font-size: 12px;
}
</style>