天天看点

规则校验(验证)那些事

首先来看看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>
           

知识点:待补充

继续阅读