我们在做前端表单提交时,经常会遇到要对表单中的数据进行校验的问题。如果用户提交的数据不合法,例如格式不正确、非数字类型、超过最大长度、是否必填项、最大值和最小值等等,我们需要在相应的地方给出提示信息。如果用户修正了数据,我们还要将提示信息隐藏起来。

  有一些现成的插件可以让你非常方便地实现这一功能,如果你使用的是knockout框架,那么你可以借助于Knockout-Validation这一插件。使用起来很简单,例如我下面的这一段代码:

ko.validation.locale('zh-CN');
ko.validation.rules['money'] = {
validator: function (val) {
if (val === '') return true;
return /^\d+(\.\d{1,2})?$/.test(val);
},
message: '输入的金额不正确'
};
ko.validation.rules['moneyNoZero'] = {
validator: function (val) {
if (val === '') return true;
return isNaN(val) || val != 0;
},
message: '输入的金额不能为0'
};
ko.validation.registerExtenders(); var model = {
MSRP: ko.observable(0),
price: ko.observable().extend({ required: true, number: true, min: 10000, money: true, moneyNoZero: true }),
licence_service_fee: ko.observable().extend({ required: true, money: true }),
purchase_tax: ko.observable().extend({ required: true, money: true }),
vehicle_tax: ko.observable().extend({ required: true, money: true }),
insurance: ko.observable().extend({ required: true, money: true }),
commercial_insurance: ko.observable().extend({ required: true, money: true }),
mortgage: ko.observable(''),
interest_discount: ko.observable(''),
allowance: ko.observable().extend({ money: true }),
special_spec_fee_explain: ko.observable(''),
has_extra_fee: ko.observable(false),
is_new_energy: ko.observable(false)
}; model.extra_fee_explain = ko.observable().extend({
required: {
onlyIf: function () {
return model.has_extra_fee() === true;
}
}
}); model.extra_fee = ko.observable().extend({
required: {
onlyIf: function () {
return model.has_extra_fee() === true;
}
},
money: {
onlyIf: function () {
return model.has_extra_fee() === true;
}
}
}); model.new_energy_allowance_explain = ko.observable().extend({
required: {
onlyIf: function () {
return model.is_new_energy() === true;
}
}
}); model.total_price = ko.computed(function () {
var _total = Number(model.price()) + Number(model.licence_service_fee()) +
Number(model.purchase_tax()) + Number(model.vehicle_tax()) +
Number(model.insurance()) + Number(model.commercial_insurance());
if (model.has_extra_fee()) {
_total += Number(model.extra_fee());
}
if (model.is_new_energy()) {
_total -= Number(model.new_energy_allowance());
}
return isNaN(_total) ? '0' : _total.toFixed(2).replace(/(\.0*$)|(0*$)/, '');
}); model.errors = ko.validation.group(model);
ko.applyBindings(model);

  更多使用方法可以查看github上的说明文档和示例。

  但是,如果我们前端使用的是React框架,如何来实现和上面knockout类似的功能呢?我们可以考虑将这一相对独立的功能抽出来,写成一个React组件。看下面的代码:

class ValidationInputs extends React.Component {
constructor(props) {
super(props);
this.state = {
isValid: true,
required: this.props.required,
number: this.props.number,
min: this.props.min,
max: this.props.max,
money: this.props.money,
data: null,
errors: ""
}
} componentWillReceiveProps(nextProps) {
var that = this;
if (this.state.data !== nextProps.data) {
return setStateQ({data: nextProps.data}, this).then(function () {
return that.handleValidation();
});
}
} handleValidation() {
var fields = this.state.data; // required validation
if(this.state.required && isNilOrEmpty(fields)){
return setStateQ({errors: '必须填写', isValid: false}, this); }
// number validation
if (this.state.number) {
if (isNaN(fields)) {
return setStateQ({errors: '请输入数字', isValid: false}, this);
}
if (!isNilOrEmpty(this.state.min) && !isNaN(this.state.min) && Number(this.state.min) > Number(fields)) {
return setStateQ({errors: '输入值必须大于等于' + this.state.min, isValid: false}, this);
}
if (!isNilOrEmpty(this.state.max) && !isNaN(this.state.max) && Number(this.state.max) < Number(fields)) {
return setStateQ({errors: '输入值必须小于等于' + this.state.max, isValid: false}, this);
}
}
// money validation
if (this.state.money) {
if (fields.length > 0 && !/^\d+(\.\d{1,2})?$/.test(fields)) {
return setStateQ({errors: '输入的金额不正确', isValid: false}, this);
}
} return setStateQ({errors: '', isValid: true}, this);
} render() {
return <span className="text-danger">{this.state.errors}</span>
}
}

  该组件支持的验证项有:

  • required:true | false 检查是否必填项。
  • number:true | false 检查输入的值是否为数字。
    • 如果number为true,可通过max和min来验证最大值和最小值。max和min属性的值都必须为一个有效的数字。
  • money:true | false 验证输入的值是否为一个有效的货币格式。货币格式必须为数字,最多允许有两位小数。

  如何使用?

  我们在父组件的render()方法中加入该组件的引用:

<div className="item">
<div className="col-xs-4">净车价:</div>
<div className="col-xs-7">
<input type="text" className="form-control" placeholder="0" value={this.state.price} onChange={this.changePrice.bind(this)}/>
<ValidationInputs ref="validation1" data={this.state.price} required="true" number="true" min="10000" max="99999999" money="true"/>
</div>
<div className="col-xs-1 text-center">元</div>
<div className="clear"></div>
</div>

  我们将price变量加到父组件的state中,并给input控件绑定onChange事件,以便用户在修改了文本框中的内容时,price变量的值可以实时传入到ValidationInputs组件中。这样,ValidationInputs组件就可以立即通过自己的handleValidation()方法对传入的数据按照预先设定的规则进行验证,并决定是否显示错误信息。

  注意,这里我们在引用ValidationInputs组件时,设置了一个ref属性,这是为了方便在父组件中获得ValidationInputs组件的验证结果(成功或失败)。我们可以在父组件中通过下面这个方法来进行判断(假设父组件中引用了多个ValidationInputs组件,并且每个引用都设置了不同的ref值):

// 父组件调用该方法来判断所有的输入项是否合法
checkInputs() {
for (var r in this.refs) {
var _ref = this.refs[r];
if (_ref instanceof ValidationInputs) {
if (!_ref.state.isValid) return false;
}
} return true;
}

  这样,我们在父组件提交数据之前,可以通过这个方法来判断所有的数据项是否都已经通过验证,如果未通过验证,则不提交表单。

  其它几个基于React的数据验证组件,不过貌似都是server端使用的:

  https://github.com/edwardfhsiao/react-inputs-validation

  https://github.com/learnetto/react-form-validation-demo

  https://learnetto.com/blog/how-to-do-simple-form-validation-in-reactjs

自定义react数据验证组件的更多相关文章

  1. 容器扩展属性 IExtenderProvider 实现WinForm通用数据验证组件

    大家对如下的Tip组件使用应该不陌生,要想让窗体上的控件使用ToolTip功能,只需要拖动一个ToolTip组件到窗口,所有的控件就可以使用该功能,做信息提示. 本博文要记录的,就是通过容器扩展属性 ...

  2. kpvalidate开辟验证组件,通用Java Web请求服务器端数据验证组件

    小菜利用工作之余编写了一款Java小插件,主要是用来验证Web请求的数据,是在服务器端进行验证,不是简单的浏览器端验证. 小菜编写的仅仅是一款非常初级的组件而已,但小菜为它写了详细的说明文档. 简单介 ...

  3. [转]MVC自定义数据验证(两个时间的比较)

    本文转自:http://www.cnblogs.com/zhangliangzlee/archive/2012/07/26/2610071.html Model: public class Model ...

  4. 验证组件——FluentValidation

          FluentValidation FluentValidation是与ASP.NET DataAnnotataion Attribute验证实体不同的数据验证组件,提供了将实体与验证分离开 ...

  5. [React]全自动数据表格组件——BodeGrid

    表格是在后台管理系统中用的最频繁的组件之一,相关的功能有数据的新增和编辑.查询.排序.分页.自定义显示以及一些操作按钮.我们逐一深入进行探讨以及介绍我的设计思路:   新增和编辑 想想我们最开始写新增 ...

  6. 使用自定义验证组件库扩展 Windows 窗体

    使用自定义验证组件库扩展 Windows 窗体             1(共 1)对本文的评价是有帮助 - 评价此主题                          发布日期 : 8/24/20 ...

  7. MVC数据验证原理及自定义ModelValidatorProvider实现无编译修改验证规则和错误信息

    Asp.net MVC中的提供非常简单易用的数据验证解决方案. 通过System.ComponentModel.DataAnnotations提供的很多的验证规则(Required, StringLe ...

  8. 通过自定义Attribute及泛型extension封装数据验证过程

    需求来源: 在日常工作中,业务流程往往就是大量持续的数据流转.加工.展现过程,在这个过程中,不可避免的就是数据验证的工作.数据验证工作是个很枯燥的重复劳动,没有什么技术含量,需要的就是对业务流程的准确 ...

  9. asp.net mvc3 数据验证(三)—自定义数据注解

    原文:asp.net mvc3 数据验证(三)-自定义数据注解         前两节讲的都是asp.net mvc3预先设定的数据注解,但是系统自由的数据注解肯定不适合所有的场合,所以有时候我们需要 ...

随机推荐

  1. python线程(二)代码部分

    使用threading创建线程: from threading import Thread def work(name): print(f"我是线程{name}") if __na ...

  2. SpringCloud的分布式配置及消息总线

    1.在搭建分布式配置时,我们大概看下分布式配置的流程 如图所示: 当一个系统中的配置文件发生改变的时候,我们需要重新启动该服务,才能使得新的配置文件生效,spring cloud config可以实现 ...

  3. 常见dos命令行

    查找本地端口占用情况 是否8080端口被占用netstat -aon|findstr "8080" 在1.txt文档当中查找java字符串type 1.txt|findstr 'j ...

  4. Windows Server 2016-DNS 新增或改进功能

    本章节补充介绍在 Windows Server 2016 中域名系统 (DNS) 服务器新增或已更改的功能相关信息,具体内容如下: 功能 新增或改进 描述 DNS 策略 新增 您可以配置 DNS 策略 ...

  5. widows10 安装1803 版本后不能访问网络上的机器解决方法

    安装Windows10 1803 版本后,发现网络上的机器好多不见了. 使用 ping  可以ping 通,但是访问网络共享提示下面错误. 这个原因是1803 中没有安装 SMB1.0 协议.因为 S ...

  6. 4年前端、2年CTO:一个非科班程序员的真实奋斗史

    1.引言   我,Scott,一家创业公司的 CTO. 从业6年却很少写文章,近一年来接触了几十个刚毕业的前端新人,也面试了100多个前端工程师和Nodejs工程师,对于前端发展的这个职业算是有些感触 ...

  7. 开放windows服务器端口-----以打开端口8080为例

    [转载]原文地址:https://blog.csdn.net/spt_dream/article/details/75014619 本文记录两个内容: 1.win7下打开端口 2.服务器(2003或者 ...

  8. java调用python程序以及向python程序传递参数

    在做项目的时候,经常会碰到这个问题,主要程序是用java写的,有些功能使用python写的,整个项目需要把java代码和python代码进行整合,在一个项目里面运行,这就涉及到java调用python ...

  9. 【重学计算机】机组D7章:总线

    1. 系统总线的特性及应用 总线概念:将计算机系统中各部件连接起来 总线分类:(外部/内部,系统/非系统,串行/并行,同步/异步...) 按用途分类: 存储总线:cpu与存储器 系统总线:连接存储总线 ...

  10. qml demo分析(photosurface-图片涅拉)

    阅读qml示例代码已有一小段时间,也陆续的写了一些自己关于qml示例代码的理解,可能由于自己没有大量的qml开发经验,总感觉复杂的ui交互qml处理起来可能会比较棘手,但事实总是会出人意料,今天我们就 ...