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 相关文章推荐
IE不出现Flash激活框的小发现的js实现方法
Sep 07 Javascript
浅析jQuery中常用的元素查找方法总结
Jul 04 Javascript
JavaScript中双叹号(!!)作用示例介绍
Apr 10 Javascript
原生javascript实现图片弹窗交互效果
Jan 12 Javascript
基于JS+Canves实现点击按钮水波纹效果
Sep 15 Javascript
AngularJS的ng-repeat指令与scope继承关系实例详解
Jan 21 Javascript
利用n 升级工具升级Node.js版本及在mac环境下的坑
Feb 15 Javascript
Bootstrap Scrollspy源码学习
Mar 02 Javascript
jQuery 1.9版本以上的浏览器判断方法代码分享
Aug 28 jQuery
JavaScript折半查找(二分查找)算法原理与实现方法示例
Aug 06 Javascript
微信小程序开发常见问题及解决方案
Jul 11 Javascript
Vue关于组件化开发知识点详解
May 13 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的面试题集
2006/11/19 PHP
PHP 5.3新特性命名空间规则解析及高级功能
2010/03/11 PHP
浅析Apache中RewriteCond规则参数的详细介绍
2013/06/30 PHP
php使浏览器直接下载pdf文件的方法
2013/11/15 PHP
php下Memcached入门实例解析
2015/01/05 PHP
PHP设计模式(九)外观模式Facade实例详解【结构型】
2020/05/02 PHP
JQUERY CHECKBOX全选,取消全选,反选方法三
2008/08/30 Javascript
日期处理的js库(迷你版)--自建js库总结
2011/11/21 Javascript
基于jquery的图片幻灯展示源码
2012/07/15 Javascript
node.js中的path.dirname方法使用说明
2014/12/09 Javascript
jQuery动画与特效详解
2015/02/01 Javascript
jquery 实现输入邮箱时自动补全下拉提示功能
2015/10/04 Javascript
JavaScript位置与大小(1)之正确理解和运用与尺寸大小相关的DOM属性
2015/12/26 Javascript
Vuejs第六篇之Vuejs与form元素实例解析
2016/09/05 Javascript
JavaScript评论点赞功能的实现方法
2017/03/13 Javascript
详解webpack es6 to es5支持配置
2017/05/04 Javascript
vue.js使用代理和使用Nginx来解决跨域的问题
2018/02/03 Javascript
javascript实现获取一个日期段内每天不同的价格(计算入住总价格)
2018/02/05 Javascript
详解在create-react-app使用less与antd按需加载
2018/12/06 Javascript
忘记ftp密码使用python ftplib库暴力破解密码的方法示例
2014/01/22 Python
python实现12306抢票及自动邮件发送提醒付款功能
2018/03/08 Python
在windows下Python打印彩色字体的方法
2018/05/15 Python
Django urls.py重构及参数传递详解
2019/07/23 Python
Python 中判断列表是否为空的方法
2019/11/24 Python
python与idea的集成的实现
2020/11/20 Python
Python 按比例获取样本数据或执行任务的实现代码
2020/12/03 Python
意大利婴儿产品网上商店:Mukako
2018/10/14 全球购物
家具厂厂长岗位职责
2014/01/01 职场文书
小学见习报告
2014/10/31 职场文书
幽默导游词开场白
2015/05/29 职场文书
2016年“5.12”护士节慰问信
2015/11/30 职场文书
幼儿园托班开学寄语(2016春季)
2015/12/03 职场文书
《打电话》教学反思
2016/02/22 职场文书
吃通javascript正则表达式
2021/04/21 Javascript
SpringBoot系列之MongoDB Aggregations用法详解
2022/02/12 MongoDB
GTX1650super好不好 gtx1650super显卡属于什么级别
2022/04/08 数码科技