js中自定义react数据验证组件实例详解


Posted in Javascript onOctober 19, 2018

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

有一些现成的插件可以让你非常方便地实现这一功能,如果你使用的是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

总结

以上所述是小编给大家介绍的js中自定义react数据验证组件实例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
用jquery方法操作radio使其默认选项是否
Sep 10 Javascript
setTimeout自动触发一个js的方法
Jan 15 Javascript
JS实现判断滚动条滚到页面底部并执行事件的方法
Dec 18 Javascript
Jquery Easyui菜单组件Menu使用详解(15)
Dec 18 Javascript
JS条形码(一维码)插件JsBarcode用法详解【编码类型、参数、属性】
Apr 19 Javascript
JS实现图片点击后出现模态框效果
May 03 Javascript
剖析Angular Component的源码示例
Mar 23 Javascript
javascript、php关键字搜索函数的使用方法
May 29 Javascript
vue在手机中通过本机IP地址访问webApp的方法
Aug 15 Javascript
使用kbone解决Vue项目同时支持小程序问题
Nov 08 Javascript
JS array数组检测方式解析
May 19 Javascript
Javascript中window.name属性详解
Nov 19 Javascript
值得收藏的八个常用的js正则表达式
Oct 19 #Javascript
深入理解移动前端开发之viewport
Oct 19 #Javascript
vue移动端html5页面根据屏幕适配的四种解决方法
Oct 19 #Javascript
Vue用v-for给循环标签自身属性添加属性值的方法
Oct 18 #Javascript
vue中v-for循环给标签属性赋值的方法
Oct 18 #Javascript
webstorm+vue初始化项目的方法
Oct 18 #Javascript
使用微信小程序开发弹出框应用实例详解
Oct 18 #Javascript
You might like
PHP中防止SQL注入攻击和XSS攻击的两个简单方法
2010/04/15 PHP
php number_format() 函数通过千位分组来格式化数字的实现代码
2013/08/06 PHP
PHP代码优化之成员变量获取速度对比
2014/02/28 PHP
php生成过去100年下拉列表的方法
2015/07/20 PHP
ZF框架实现发送邮件的方法
2015/12/03 PHP
php面向对象编程self和static的区别
2016/05/08 PHP
PHP递归实现快速排序的方法示例
2017/12/18 PHP
JavaScript表单常用验证集合
2008/01/16 Javascript
不一样的文字闪烁 轮番闪烁
2009/11/11 Javascript
不同浏览器对回车提交表单的处理办法
2010/02/13 Javascript
javascript 树形导航菜单实例代码
2013/08/13 Javascript
jquery分页插件jquery.pagination.js使用方法解析
2016/04/01 Javascript
利用Chrome DevTools直接调试Node.js和JavaScript的方法详解(并行)
2017/02/16 Javascript
Easyui Datagrid自定义按钮列(最后面的操作列)
2017/07/13 Javascript
Vuejs监听vuex中值的变化的方法示例
2018/12/02 Javascript
Vue中的循环及修改差值表达式的方法
2019/08/29 Javascript
微信小程序跨页面传递data数据方法解析
2019/12/13 Javascript
[06:53]2018DOTA2国际邀请赛寻真——勇于创新的Vici Gaming
2018/08/14 DOTA
python执行get提交的方法
2015/04/29 Python
详解Python函数可变参数定义及其参数传递方式
2017/08/02 Python
python编写Logistic逻辑回归
2020/12/30 Python
代码详解django中数据库设置
2019/01/28 Python
Python语言检测模块langid和langdetect的使用实例
2019/02/19 Python
基于python-pptx库中文文档及使用详解
2020/02/14 Python
解决pycharm中的run和debug失效无法点击运行
2020/06/09 Python
用python-webdriver实现自动填表的示例代码
2021/01/13 Python
W3C公布最新的HTML5标准草案
2008/10/17 HTML / CSS
HTML5拖拉上传文件的简单实例
2017/01/11 HTML / CSS
英国领先的在线药房:Pharmacy First
2017/09/10 全球购物
毕业生的自我评价
2013/12/30 职场文书
仓库管理计划书
2014/05/04 职场文书
银行柜员求职自荐书
2014/06/18 职场文书
机关作风建设整改方案
2014/10/27 职场文书
个人简历自我评价怎么写
2015/03/10 职场文书
我是特种兵观后感
2015/06/11 职场文书
Nginx安装配置详解
2022/06/25 Servers