首先来看一下element给出的案例

<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>

需要关注的点:

三个组件

el-form  el-form-item  el-input

       校验规则在form组件中,具体的值绑定至input,通过操作form节点的.validate方法来实现校验,具体的数据和绑定看下面代码

        

<template><div><WWQBlock class="form"><WWQForm ref="formItems" :model="formData" :rules="ruleValidate"><WWQFromItem label="姓名 :" prop="value1"><WWQInputplaceholder="请输入内容..."inputType="text"v-model="formData.value1"></WWQInput></WWQFromItem><WWQFromItem label="密码 :" prop="value2"><WWQInputplaceholder="请输入内容"inputType="password"v-model="formData.value2"></WWQInput></WWQFromItem><WWQFromItem label="爱好 :" prop="value3"><WWQSelect v-model="formData.value3" :data="selectData"></WWQSelect></WWQFromItem><div></div></WWQForm><WWQBlock><WWQButtontype="success"size="small"@click="changeButton"radius="10px">提交</WWQButton></WWQBlock></WWQBlock></div>
</template><script>
export default {name: "App",data() {return {formData: {value1: "",value2: "",value3: "",},ruleValidate: {value1: [{ required: true, message: "用户名不能为空", trigger: "blur" }],value2: [{ required: true, message: "放心输入自己的隐私吧!", trigger: "blur" },{ required: true, min: 0, max: 8, message: "超出限制了...",trigger: "change"     },],value3: [{ required: true, message: "总得有个特长什么的吧?", trigger: "blur" },],},}},methods: {changeButton() {console.log(this.formData);this.$refs.formItems.validate() // 验证方法.then((res) => {console.log(res);});},},
};
</script>

可以看到 el-form  el-form-item  el-input 这三个组件时互相嵌套关系,并非简单的父子组件,想要查看只能通过插槽,但是还有一种更灵活的办法,

那就是 provide 广播 和  inject 派发

首先需要定义一个事件总线,以供全局使用


function broadcast(componentName, eventName, params) {// 循环子节点找到名称一样的子节点 否则 递归 当前子节点this.$children.map((child) => {if (componentName === child.$options.name) {child.$emit.apply(child, [eventName].concat(params));} else {broadcast.apply(child, [componentName, eventName].concat(params));}});
}
export default {methods: {/*** 派发 (向上查找) (一个)* @param componentName // 需要找的组件的名称* @param eventName // 事件名称* @param params // 需要传递的参数*/dispatch(componentName, eventName, params) {let parent = this.$parent || this.$root; //$parent 找到最近的父节点 $root 根节点let name = parent.$options.name; // 获取当前组件实例的name// 如果当前有节点 && 当前没名称 且 当前名称等于需要传进来的名称的时候就去查找当前的节点// 循环出当前名称的一样的组件实例while (parent && (!name || name !== componentName)) {parent = parent.$parent;if (parent) {name = parent.$options.name;}}// 有节点表示当前找到了name一样的实例if (parent) {parent.$emit.apply(parent, [eventName].concat(params));}},/*** 广播 (向下查找) (广播多个)* @param componentName // 需要找的组件的名称* @param eventName // 事件名称* @param params // 需要传递的参数*/broadcast(componentName, eventName, params) {broadcast.call(this, componentName, eventName, params);},},
};

在父组件我们这样做

  provide() {// 这里相当于把整个组件实例广播出去return {form: this,};},

子组件中通过inject获取

 inject: ["form"],

这样一来三个组件可以互相通信,并且彼此更改组件之间的值,

form组件在接受到rule和model之后干了什么?

<template><form action=""><slot></slot></form>
</template><script>
export default {name: "WWQForm",provide() {return {form: this,};},data() {return {fields: [], // 储存当前的 form-item的实例};},created() {let that = this;this.$on("on-form-item-add", (item) => {if (item) {that.fields.push(item);}});this.$on("on-form-item-remove", (item) => {if (item.prop) {that.fields.splice(that.fields.indexOf(item), 1);}});},methods: {resetFields() {this.fields.forEach((field) => {field.resetField();});},validate(callback) {return new Promise((resolve) => {let valid = true; // 默认是通过let count = 0; // 来匹配当前是否是全部检查完this.fields.forEach((field) => {// 每个实例都会有 validation 的校验的方法field.validation("", (error) => {if (error) {valid = false;}// 通过当前检查完所有的form-item的时候才会调用if (++count === this.fields.length) {resolve(valid); // 方法使用thenif (typeof callback === "function") {callback(valid); // 直接调用注入的回调方法} }});});}); }, },};

可以看到该组件广播了两个事件,并且定义了验证方法,遍历逐一校验表单项,

        form-item做了啥?

<template><div class="wwq-form-item"><label class="wwq-label" v-if="label" for="">{{ label }}</label><slot></slot><Transition name="tip"><span class="wwq-form-item-message" v-if="validateState === 'error'">{{ validateMessage }}</span></Transition></div>
</template><script>
import Emitter from "../../emitter";
import schema from "async-validator";
export default {name: "WWQFromItem",mixins: [Emitter],inject: ["form"],props: {label: String,prop: String,},computed: {fieldValue() {return this.form.model[this.prop];},},data() {return {initialValue: "", // 储存默认值isRequired: false, // 当前的是否有问题validateState: "", // 是否校验成功validateMessage: "", // 校验失败文案};},methods: {setRules() {let that = this;let rules = this.getRules(); //拿到父组件过滤后当前需要使用的规则if (rules.length) {this.isRequired = rules.some((rule) => {return rule.required;});}this.$on("on-form-blur", that.onFieldBlur);this.$on("on-form-change", that.onFieldChange);},getRules() {let that = this;let rules = that.form.rules;rules = rules ? rules[that.prop] : [];return [].concat(rules || []); //这种写法可以让规则肯定是一个数组的形式},onFieldBlur() {this.validation("blur");},onFieldChange() {this.validation("change");},getFilteredRule(trigger) {let rules = this.getRules();// !res.trigger 没有调用方式的时候默认就校验的// filter 过滤出当前需要的规则return rules.filter((res) => !res.trigger || res.trigger.indexOf(trigger) !== -1);},validation(trigger, callback = function () {}) {let rules = this.getFilteredRule(trigger);// 判断当前是否有规则if (!rules || rules.length === 0) {return;}this.validateState = "validating";var validator = new schema({ [this.prop]: rules });// firstFields: true 只会校验一个validator.validate({ [this.prop]: this.fieldValue },{ firstFields: true },(errors) => {this.validateState = !errors ? "success" : "error";this.validateMessage = errors ? errors[0].message : "";callback(this.validateMessage);});},resetField() {this.form.model[this.prop] = this.initialValue;},},// 组件渲染时,将实例缓存在 Form 中mounted() {// 如果没有传入 prop,则无需校验,也就无需缓存if (this.prop) {this.dispatch("WWQForm", "on-form-item-add", this);// 设置初始值,以便在重置时恢复默认值this.initialValue = this.fieldValue;// 添加表单校验this.setRules();}},// 组件销毁前,将实例从 Form 的缓存中移除beforeDestroy() {this.dispatch("WWQForm", "on-form-item-remove", this);},
};
</script>

通过自身接受的字段从父级获取表单绑定的value,并广播交互事件

input组件做的事

<template><div class="wwq-input"><input:type="inputType":value="defaultValue"@input="handleInput"@blur="handleBlur":placeholder="placeholder"/></div>
</template><script>
import Emitter from "../../emitter";
export default {name: "WWQInput",mixins: [Emitter],data() {return {defaultValue: this.inputVal,};},props: {inputType: {type: String,default: "text",},value: String,placeholder: String,},watch: {value(val) {this.defaultValue = val;},},methods: {handleInput(event) {this.defaultValue = event.target.value;this.$emit("input", event.target.value);// 将当前的值发送到 aiFormItem 进行校验this.dispatch("WWQFromItem", "on-form-change", event.target.value);},handleBlur(event) {// vue 原生的方法 return 出去this.$emit("blur", event.target.value);// 将当前的值发送到 aiFormItem 进行校验this.dispatch("WWQFromItem", "on-form-blur", event.target.value);},},
};
</script>

表单交互事件派发给 form-item 组件,改变绑定value的同时触发校验

校验失败的话 form-item 会弹出警告信息。

注意:

        绑定至父级节点form的rule一定要符合规范~

  ruleValidate: {value1: [{ required: true, message: "用户名不能为空", trigger: "blur" }],value2: [{ required: true, message: "放心输入自己的隐私吧!", trigger: "blur" },{ required: true, min: 0, max: 8, message: "超出限制了...",trigger: "change" },],value3: [{ required: true, message: "总得有个特长什么的吧?", trigger: "blur" },],},

前端 表单校验的使用和实现相关推荐

  1. 【前端2】js:原始类型,运算符,调试,页面加载,轮播图,Bom(对象,时钟),Dom(全选全不选,省市级联,隔行/触摸换色,表单校验)

    文章目录 1.js两种引入:js最终要引入到html在浏览器中运行 2.js五大原始类型:undefined 3.js的运算符和流程控制:js不支持单&和单|性能低 4.案例_99乘法表:So ...

  2. BCSP-玄子前端开发之JavaScript+jQuery入门CH13_表单校验

    BCSP-玄子前端开发之JavaScript+jQuery入门CH13_表单校验 4.13 表单验证 4.13.1 为什么要表单验证 保证输入的数据符合要求 减轻服务器的压力 [外链图片转存失败,源站 ...

  3. web前端必学功法之一:表单校验(1)

    web前端必学功法之一:表单校验 案例效果: 这里的布局采用的是bootstrap布局 <div class="container" style="margin-t ...

  4. web前端必学功法之一:表单校验(2)

    web前端必学功法之一:表单校验(2) 这里采用另一种写法,jQuery写法,在用jQuery写法之前,一定要引入jquery.js. <div class="container&qu ...

  5. 【前端3】jquary:页面加载,选择器,隔行换色,Dom,全选,动画,遍历,广告/抽奖,表单校验插件

    文章目录 1.jquery框架引入:$("mydiv") 当成id选择器 2.jquery版本/对象:$(js对象) -> jquery对象 3.jquery的页面加载事件: ...

  6. activeform表单中的旧数据怎么显示_三分钟为你细数 Vue el-form 表单校验的坑点

    背景 Vue 的 el-form 提供了表单校验功能,通过 :rules 属性设置校验规则,并通过 el-form-item 的 prop 属性绑定校验规则.通过封装,让前端校验更方便.具体使用过程中 ...

  7. vue form validate 多个input_Vue表单校验插件Vuerify使用详细教程及示例

    点击右上方红色按钮关注"web秀",让你真正秀起来 前言 表单校验,在开发中是非常常见的,为了防止用户误操作,填写错误数据,亦或是防止用户恶意提交数据等,都需要前端同学来做一些简单 ...

  8. js-最常用的js表单校验1

    最近写了无数各种形式的表单,记录下奇奇怪怪的校验规则~ 一:首先是element自带的rules校验规则: element作为常用框架,自带rules属性简单易懂,官方文档一目了然,不再赘述,应付常用 ...

  9. Day84.尚好房 — 功能提取、页面封装、jquery-validate表单校验、完成角色 | 用户管理模块

    目录 角色管理模块 一.角色管理代码封装  ★ 1.封装BaseDao 2.封装BaseDao 3.封装BaseServiceImpl 4.封装Controller层 二.前端页面封装 1.封装头部c ...

最新文章

  1. 把磁盘崩溃了,总是进去维护模式,却删除不了fstab文件中的内容
  2. [JLOI 2012]树
  3. 取成本中心-生产订单
  4. 深入理解Netty高性能网络框架
  5. CSS 单行溢出文本显示省略号...的方法(兼容IE FF)(转)
  6. Java——设计模式(简单工厂模式)
  7. git报错:‘fatal:remote origin already exists‘怎么处理?附上git常用操作以及说明。
  8. 《DeepLearning.ai 深度学习笔记》发布,黄海广博士整理
  9. 超实用的浏览器插件:CSDN 一键搜索、自定义工具、全站去广告、一键美化等
  10. Make GNN Great Again: GNN 上的预训练和自监督学习
  11. GA遗传算法入门到掌握
  12. CSS 二十年发展简史
  13. Linux中的任务调度
  14. ROS@Ubuntu16.04体验记录
  15. 天涯论坛--只看楼主
  16. Excel怎么锁定单元格
  17. HFSS周期结构超表面结构单元仿真
  18. Linux内核模块编程指南(一)(转)
  19. Scientists discover how mosquitoes detect human sweat-由于嗅觉受体的存在,蚊子会被人体汗液中的乳酸所吸引,
  20. Watershed算法

热门文章

  1. 创想联盟常用软件工具盘V1.1
  2. 洛谷 P2814 家谱
  3. 奶块的服务器为什么在修复,奶块有几个服务器 | 手游网游页游攻略大全
  4. android webview mailto,如何处理mailto:在android webview中
  5. Arduino的Serial.println()
  6. 连接redis服务器提示:Redis Client On Error: Error: connect ECONNREFUSED 127.0.0.1:6379 Config right?
  7. 5.3字符数组字符串
  8. jsf--小项目--爱群小店
  9. 一种电磁兼容半电波暗室设计和实现
  10. 想不想修真获取服务器配置文件,想不想修真 全地图属性要求都在这了,各位玩家请注意收藏!...