- el-form:管理数据模型(model)和校验规则(rules),提供全局的校验方法(validate)
- el-form-item:显示 label 标签,执行校验(prop),显示校验结果
element:绑定数据模型(v-model),通知 formItem 进行校验
<template><div><el-form :model="ruleForm" :rules="rules" ref="ruleForm"><el-form-item label="用户名" prop="name"><el-input v-model="ruleForm.name"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-input type="password" v-model="ruleForm.password"></el-input></el-form-item><el-form-item><el-button @click="login('ruleForm')">登录</el-button></el-form-item></el-form></div></template><script>export default {data() {return {// 数据模型ruleForm: {name: "",password: ""},// 校验规则rules: {name: [{ required: true, message: "请输入用户名" }],password: [{ required: true, message: "请输入密码" }]}};},methods: {login(formName) {this.$refs[formName].validate(valid => {if (valid) {alert("submit!");} else {alert("error submit!!");}});}}};</script>
<!--MyInput.vue--><template><div><input :type="type" :value="value" @input="inputHandler" /></div></template><script>export default {name: "MyInput",props: {type: {type: String,default: "text"},value: {type: String,default: ""}},methods: {inputHandler(e) {// 仅派发事件this.$emit("input", e.target.value);// 通知校验// 为什么这里是this.$parent.$emit,而不是this.$emit?this.$parent.$emit("validate");}}};</script>
<!--MyFormItem.vue--><template><div><label v-if="label">{{label}}</label><div><!--这里的插槽插入MyInput.vue内容--><slot></slot><!-- 校验错误信息 --><p v-if="validateStatus === 'error'">{{errorMes}}</p></div></div></template><script>// 借助“async-validator”进行表单校验import Schema from "async-validator";export default {name: "MyFormItem",// 注入'from',为了使用form提供的数据模型【model】和校验规则【rules】inject: ["form"],props: {label: {type: String,default: ""},// 用于获取指定字段值和校验规则prop: {type: String,default: ""}},data() {return {errMes: ""};},mounted() {// 监听Input组件的“this.$parent.$emit(’validate‘)”// 因为MyFormItem组件的input位置一开始只是个插槽,没有<my-input/>标签,所以无法以"<my-input @validate=''/>"监听事件this.$on("validate", () => {this.validate();});},methods: {// 单项校验validate() {// 1.获取值和校验规则const value = this.form.model[this.prop];const rule = this.form.rules[this.prop];// 2.创建Schema实例 {username: rules}const schema = new Schema({ [this.prop]: rule });// 3.执行校验,校验对象,回调函数// validate返回校验结果Promisereturn schema.validate({ [this.prop]: value }, errors => {if (errors) {this.errMes = errors[0].message;} else {this.errMes = "";}});}}};</script>
<!--MyForm.vue--><template><div><!-- 插入<my-form-item/>的内容 --><slot></slot></div></template><script>export default {name: "MyForm",// 把form实例提供出去,以便后代组件使用它的数据模型和校验规则provide() {return {form: this};},props: {model: {type: Object,required: true},rules: {type: Object}},methods: {validate(cb) {// 全局校验// 1.不是所有项都需要校验, MyFormItem有prop属性才需要校验// 2. tasks是promise数组const tasks = this.$children.filter(item => item.prop).map(item => item.validate())// 3. 所有MyFormItem必须全通过, 整个表单才是验证通过Promise.all(tasks).then(() => cb(true)).catch(() => cb(false));}}};</script>
参考资料
