注:本文的demo实现都是用了笔者自己搭建的vue、react的初始化demo项目,方便平时做实现,写demo用。每次都要从0搭建实在是太恶心了,如果大家也用得上,直接clone走。
react-demo(create-react-app@1.5.2 + antd@3.6.4 + react@16.4.1 + react-router-dom@4.3.1)
vue-demo(vue-cli@2.9.3 + element-ui@2.4.1 + vue@2.5.2 + vue-router@3.0.1)
表单复杂校验规则的一个demo说明
姓名:
- 必填
- 最多5个字符
- 不能与【父亲姓名】一致
昵称:
- 必填
- 最多3个字符
- 【姓名】修改会触发此字段修改,截取【姓名】的前三个字符
- 可自己修改
父亲姓名:
- 必填
- 最多5个字符
- 不能与【姓名】一致
vue(ElementUI)实现:
<template>
<div class="formvalidate">
<p>实现表单的关联校验</p>
<el-row>
<el-col :span="12">
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px">
<el-form-item label="姓名" prop='name'>
<el-input v-model="ruleForm.name"></el-input>
<p class="note">请输入最多5个字符,且不能和父亲姓名一样</p>
</el-form-item>
<el-form-item label="昵称" prop='nick' required>
<el-input v-model="nickName"></el-input>
<p class="note">请输入最多3个字符</p>
</el-form-item>
<el-form-item label="父亲姓名" prop='father'>
<el-input v-model="ruleForm.father"></el-input>
<p class="note">请输入最多5个字符,且不能和子女姓名一样</p>
</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>
<pre>{{result}}</pre>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: 'FormValidate',
data() {
return {
ruleForm: {
name: '',
nick: '',
father: '',
},
result: '',
rules: {
name: [
{ required: true, message: '请输入内容', trigger: 'change' },
{ max: 5, message: '最多5个字符', trigger: 'change' },
{ validator: (rule, value, callback) => { // ======划重点======
if (value === this.ruleForm.father) {
callback(new Error('不能与父亲姓名一致'));
} else {
callback();
}
}, trigger: 'change' },
],
nick: [
{ required: true, message: '请输入内容', trigger: 'change' },
{ max: 3, message: '最多3个字符', trigger: 'change' },
],
father: [
{ required: true, message: '请输入内容', trigger: 'change' },
{ max: 5, message: '最多5个字符', trigger: 'change' },
{ validator: (rule, value, callback) => { // ======划重点======
if (value === this.ruleForm.name) {
callback(new Error('不能与姓名一致'));
} else {
callback();
}
}, trigger: 'change' },
],
},
}
},
computed: { // ======划重点======
nickName:{
set(value){
this.ruleForm.nick = value;
},
get(){
const val = this.ruleForm.name.substring(0,3);
this.ruleForm.nick = val;
return val;
},
}
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.result = JSON.stringify(this.ruleForm,null,2);
} else {
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
},
};
</script>
<style scoped>
.note {
line-height: 1;
color: #999;
font-size: 12px;
margin: 10px 0 0;
}
</style>
注:element的官方文档推荐了async-validator作为rules规则的文档参考,笔者还没有详细研究,猜测element用了此库。另外antd的验证规则格式也是这个样子的,所以也有用了这个库的可能。想要自己实现一套form校验规则的同学,可以研究一下。
react(antd)实现:
import React, { Component } from 'react';
import { Form, Input, Button } from 'antd';
import './style.less';
const FormItem = Form.Item;
const formItemLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 8 },
};
const formTailLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 8, offset: 4 },
};
class FormValidate extends Component {
changeName(value) {
this.props.form.setFieldsValue({ nick: value.substring(0, 3) });
}
render() {
const { getFieldDecorator } = this.props.form;
return (
<div className="FormValidate">
<h1>实现表单的关联校验</h1>
<Form>
<FormItem {...formItemLayout} label='姓名' extra='请输入最多5个字符,且不能和父亲姓名一样'>
{getFieldDecorator('name', {
rules: [
{ required: true, message: '请输入内容', trigger: 'change' },
{ max: 5, message: '最多5个字符', trigger: 'change' },
{
validator: (rule, value, callback) => { // ======划重点======
const form = this.props.form;
if (value && value === form.getFieldValue('father')) {
callback('不能与父亲姓名一致');
} else {
callback();
}
}, trigger: 'change'
},
],
})(<Input placeholder="Please input your name" onChange={e => this.changeName(e.target.value)} />)}
</FormItem>
<FormItem {...formItemLayout} label='昵称' extra='请输入最多3个字符'>
{getFieldDecorator('nick', {
rules: [
{ required: true, message: '请输入内容', trigger: 'change' },
{ max: 3, message: '最多3个字符', trigger: 'change' },
],
})(<Input placeholder="Please input your name" />)}
</FormItem>
<FormItem {...formItemLayout} label='父亲姓名' extra='请输入最多5个字符,且不能和子女姓名一样'>
{getFieldDecorator('father', {
rules: [
{ required: true, message: '请输入内容', trigger: 'change' },
{ max: 5, message: '最多5个字符', trigger: 'change' },
{
validator: (rule, value, callback) => { // ======划重点======
const form = this.props.form;
if (value && value === form.getFieldValue('name')) {
callback('不能与姓名一致');
} else {
callback();
}
}, trigger: 'change'
},
],
})(<Input placeholder="Please input your name" />)}
</FormItem>
<FormItem {...formTailLayout}>
<Button type="primary">提交</Button>
</FormItem>
</Form>
</div>
);
}
}
export default Form.create()(FormValidate);