首先来看看Element-UI的表单验证
Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可。
普通验证
例:仅以输入框、下拉框以及复选框举例
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
//输入框
<el-form-item label="活动名称" prop="name">
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
//下拉框
<el-form-item label="活动区域" prop="region">
<el-select v-model="ruleForm.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
//复选框
<el-form-item label="活动性质" prop="type">
<el-checkbox-group v-model="ruleForm.type">
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</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() {
return {
ruleForm: {
name: '',
region: '',
type: []
},
rules: {
name: [
{ required: true, message: '请输入活动名称', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
region: [
{ required: true, message: '请选择活动区域', trigger: 'change' }
],
type: [
{ type: 'array', required: true, message: '请至少选择一个活动性质', trigger: '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>
自定义校验规则
//status-icon状态图标显示
<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>
//年龄框(判断年龄是否是数字,且大于18岁)
<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() {
//rule里面可以截取到行号
var checkAge = (rule, value, callback) => {
//非空判定
if (!value) {
return callback(new Error('年龄不能为空'));
}
//setTimeout()那些事
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 !== '') {
//validateField 部分字段的校验(不为空时校验‘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>
setTimeout()
:由setTimeout()引出的那些事 --> 首先js设计的重点:js是没有多线程的,js引擎的执行是单线程执行,但
- js引擎是单线程的,可是浏览器却可以是多线程的,js引擎只是浏览器的一个线程而已。定时器计时,网络请求,浏览器渲染等等,都是由不同的线程去完成的
规则校验(验证)那些事 - js引擎单线程执行的,它是基于事件驱动的语言,它的执行顺序是遵循一个叫做事件队列的机制
- 从图中我们可以看出:浏览器有各种各样的线程,比如事件触发器,网络请求,定时器等等
- 线程的联系都是基于事件的:js引擎处理到与其他线程相关的代码,就会分发给其他线程,他们处理完之后,需要js引擎计算时就是在事件队列里面添加一个任务
- 这个过程中,js并不会阻塞代码等待其他线程执行完毕,而且其他线程执行完毕后添加事件任务告诉js引擎执行相关操作,这就是js的异步编程模型
动态增减表单项验证
<el-form :model="dynamicValidateForm" ref="dynamicValidateForm" label-width="100px" class="demo-dynamic">
//trigger: ['blur', 'change'],trigger是可以拥有两个事件的
<el-form-item
prop="email"
label="邮箱"
:rules="[
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }
]"
>
<el-input v-model="dynamicValidateForm.email"></el-input>
</el-form-item>
<el-form-item
v-for="(domain, index) in dynamicValidateForm.domains"
:label="'域名' + index"
:key="domain.key"
:prop="'domains.' + index + '.value'"
:rules="{
required: true, message: '域名不能为空', trigger: 'blur'
}"
>
<el-input v-model="domain.value"></el-input><el-button @click.prevent="removeDomain(domain)">删除</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('dynamicValidateForm')">提交</el-button>
<el-button @click="addDomain">新增域名</el-button>
<el-button @click="resetForm('dynamicValidateForm')">重置</el-button>
</el-form-item>
</el-form>
<script>
export default {
data() {
return {
dynamicValidateForm: {
//domains: json数组对象
domains: [{
value: ''
}],
email: ''
}
};
},
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();
},
removeDomain(item) {
//indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置
var index = this.dynamicValidateForm.domains.indexOf(item)
if (index !== -1) {
this.dynamicValidateForm.domains.splice(index, 1)
}
},
addDomain() {
this.dynamicValidateForm.domains.push({
value: '',
key: Date.now()
});
}
}
}
</script>
你想知道的
indexOf()
:
- 返回某个指定的字符串值在字符串中首次出现的位置。
- stringObject.indexOf(searchvalue规定需检索的字符串值 必须,fromindex规定在字符串中开始检索的位置 它的合法取值是 0 到 stringObject.length - 1)
- indexOf() 方法对大小写敏感!
- 如果要检索的字符串值没有出现,则该方法返回 -1。
你想知道的
splice()
:
- splice() 方法用于添加或删除数组中的元素。
- array.splice(index必需 规定从何处添加/删除元素 数字,howmany应该删除多少元素,item1,…,itemX要添加到数组的新元素)
- 返回值:如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组。
- fruits.splice(2,1,“Lemon”,“Kiwi”);移除数组的第三个元素,并在数组第三个位置添加新元素
- fruits.splice(2,2);从第三个位置开始删除数组后的两个元素
由官网得到的验证拓展 验证一
//只留下跟验证有关的
//注意:model="firstForm"的绑定
<el-form :model="firstForm" ref="firstForm" :rules="createRules" :disabled="isShow&&!$store.state.isTabClick">
<el-table :data="firstForm.domains" :size="$size" :row-class-name="rowClassName" empty-text=" "
style="width: 100%" class="twoTable">
<el-table-column label="" width="auto" align="center">
</el-table-column>
<el-table-column label="" width="auto" align="center">
<template slot-scope="scope">
//通过:rules="createRules.attributeSign"来选择哪个验证规则和限定条件
//注意prop绑定
<el-form-item :prop="'domains.'+ scope.$index +'[0].attributeSign'"
:rules="createRules.attributeSign">
<el-select v-model="scope.row[0].attributeSign" placeholder="请选择属性标示"
@change="changeOption(scope.$index)" :size="$size">
<el-option label="列标头" value="0"></el-option>
<el-option label="属性列" value="1"></el-option>
<el-option label="指标列" value="2"></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="" width="auto" align="center">
<template slot-scope="scope">
<el-form-item :prop="'domains.'+ scope.$index +'[0].value'" :rules="createRules.value">
//value-format="yyyy-MM" 可以直接将组件里的日期直接格式为需要的
<el-date-picker v-model="scope.row[0].value" type="month" placeholder="选择月"
v-if="scope.row[0].attributeSign == '2'" :size="$size" style="width: 100%;"
value-format="yyyy-MM">
</el-date-picker>
<el-input v-model="scope.row[0].value" v-else :size="$size"></el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="" width="auto" align="center">
<template slot-scope="scope">
<el-form-item :prop="'domains.'+ scope.$index +'[1].value'" :rules="createRules.valueSortId">
<el-input-number v-model="scope.row[1].value" :min="0" :max="200" :size="$size">
</el-input-number>
</el-form-item>
</template>
</el-table-column>
</el-table>
</el-form>
<script>
export default {
data() {
let that = this
return {
//注:该表单的model定义必须如此,因为我们要找到具体的数据
firstForm: { domains: [] },//行数据,
createRules: {//数据校验
attributeSign: [//属性表示校验
{
required: true,
validator: function (rule, value, callback) {
if (!value) {
return callback(new Error('请输入内容'));
} else {
return callback();
}
},
trigger: 'change'
}
],
value: [//一级列名称校验
{
required: true,
validator: function (rule, value, callback) {
if (!value) {
return callback(new Error('请输入内容'));
} else if (that.isDataRepeat(rule, value)) { //判断是否重复
return callback(new Error('一级列不能重复'))
} else {
return callback();
}
},
trigger: 'blur'
}
],
valueSortId: [//排序序列号校验
{
required: true,
validator: function (rule, value, callback) {
if (!value && value != 0) {
return callback(new Error('请输入内容'));
} else {
return callback();
}
},
trigger: 'blur'
}
],
},
},
methods: {
//一节列名称去重
isDataRepeat(rule, data) {
let str = rule.field.split('.')[1];
let num = parseInt(str.substring(0, str.indexOf("[")))
let count = 0;
let attributeSign = this.firstForm.domains[num][0].attributeSign;
for (let i = 0; i < this.firstForm.domains.length; i++) {
if (data == this.firstForm.domains[i][0].value) {
if (attributeSign == this.firstForm.domains[i][0].attributeSign) {
count++;
}
}
}
return count > 1 ? true : false;
},
}
}
}
</script>
你想知道的
split()
:
- split() 方法用于把一个字符串分割成字符串数组。
- string.split(separator可选 字符串或正则表达式 从该参数指定的地方分割 string Object,limit可选 该参数可指定返回的数组的最大长度)
- 返回值:一个字符串数组。该数组是通过在 separator 指定的边界处将字符串 string Object 分割成子串创建的。返回的数组中的字串不包括 separator 自身。
- 如果把空字符串 ("") 用作 separator,那么 stringObject 中的每个字符之间都会被分割。
- split() 方法不改变原始字符串。
由官网得到的验证拓展 验证二(某杨写法)
<el-form :model="secondForm" ref="secondForm" :rules="createRules" :disabled="isShow&&!$store.state.isTabClick">
<el-table :data="secondForm.domains" :size="$size" :row-class-name="rowClassName" empty-text=" "
style="width: 100%" class="twoTable">
<el-table-column label="" width="auto" align="center">
<template slot-scope="scope">
<el-form-item :prop="'attributeSign' + scope.$index">
<el-select v-model="scope.row[0].attributeSign"
@change="changeOption(scope.$index,scope.row[0].attributeSign)" placeholder="请选择属性标示"
:size="$size">
<el-option label="列标头" value="0"></el-option>
<el-option label="属性列" value="1"></el-option>
<el-option label="指标列" value="2"></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="" width="auto" align="center">
<template slot-scope="scope">
<el-form-item :prop="'value'+scope.$index">
<el-select v-model="scope.row[0].value" @change="changeValue($event,scope.$index)"
placeholder="请选择上级列名称" :size="$size">
<el-option v-for="(item,index) in pNameData[scope.$index]" :key="index"
:label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="" width="auto" align="center">
<template slot-scope="scope">
<el-form-item :prop="'secName'+scope.$index">
<el-input v-model="scope.row[1].value" :size="$size"></el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="" width="auto" align="center">
<template slot-scope="scope">
<el-form-item :prop="'jizhunlie'+scope.$index">
<el-select :disabled="scope.row[0].attributeSign=='2'?false:true"
v-model="scope.row[2].value" placeholder="请选择基准列标示" :size="$size">
<el-option label="不是基准列" value="0"></el-option>
<el-option label="是基准列" value="1"></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="" width="auto" align="center">
<template slot-scope="scope">
<el-form-item :prop="'valueSortId'+scope.$index">
<el-input-number v-model="scope.row[3].value" :min="0" :max="200" :size="$size">
</el-input-number>
</el-form-item>
</template>
</el-table-column>
</el-table>
</el-form>
<script>
export default {
data() {
let that = this
return {
//注:该表单的model定义必须如此,因为我们要找到具体的数据
secondForm: { domains: [] },//行数据,
},
methods: {
//基准列去重和二级列名称去重
isDataRepeat(rule, data, flag) {
let num = parseInt(rule.field.substring(flag.length, rule.field.length))
let count = 0;
let attributeSign = this.secondForm.domains[num][0].attributeSign;
let pName = this.secondForm.domains[num][0].value;
for (let i = 0; i < this.secondForm.domains.length; i++) {
if (data == this.secondForm.domains[i][1].value || (data == '1' && data == this.secondForm.domains[i][2].value)) {
if (attributeSign == this.secondForm.domains[i][0].attributeSign && pName == this.secondForm.domains[i][0].value) {
count++;
}
}
}
return count > 1 ? true : false;
},
},
computed: {
//验证
createRules() {
let rules = {};
const _that = this;
this.secondForm.domains.forEach((item, index) => {
rules = Object.assign(rules, {
[`attributeSign${index}`]: [{
validator: function (rule, value, callback) {
if (!item[0].attributeSign) {
return callback(new Error('请输入内容'));
} else {
return callback();
}
},
trigger: 'change'
}],
[`value${index}`]: [{
validator: function (rule, value, callback) {
if (!item[0].value) {
return callback(new Error('请输入内容'));
} else {
return callback();
}
},
trigger: 'change'
}],
[`secName${index}`]: [{
validator: function (rule, value, callback) {
if (!item[1].value) {
return callback(new Error('请输入内容'));
} else if (_that.isDataRepeat(rule, item[1].value, 'secName')) {
return callback(new Error('二级列名称不能重复'))
} else {
return callback();
}
},
trigger: 'blur'
}],
[`jizhunlie${index}`]: [{
validator: function (rule, value, callback) {
if (!item[2].value && item[0].attributeSign == '2') {
return callback(new Error('请输入内容'));
} else if (_that.isDataRepeat(rule, item[2].value, "jizhunlie") && item[0].attributeSign == '2') {
return callback(new Error('只能有一个基准列'))
} else {
return callback();
}
},
trigger: 'change'
}],
[`valueSortId$[index]`]: [{
validator: function (rule, value, callback) {
if (!item[1].value) {
return callback(new Error('请输入内容'));
} else {
return callback();
}
},
trigger: 'blur'
}]
})
})
return rules;
}
}
}
</script>
知识点:待补充