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 相关文章推荐
用javascript控制iframe滚动的代码
Apr 10 Javascript
javascript getElementsByClassName 和js取地址栏参数
Jan 02 Javascript
Javascript 中 null、NaN和undefined的区别总结
Apr 10 Javascript
Javascript 绘制 sin 曲线过程附图
Aug 21 Javascript
jquery结合CSS使用validate实现漂亮的验证
Jan 29 Javascript
js实现创建删除html元素小结
Sep 30 Javascript
js获取Html元素的实际宽度高度的方法
May 19 Javascript
HTML页面定时跳转方法解析(2种任选)
Dec 22 Javascript
webpack vue 项目打包生成的文件,资源文件报404问题的修复方法(总结篇)
Jan 09 Javascript
JavaScript数组排序小程序实现解析
Jan 13 Javascript
vscode+gulp轻松开发小程序的完整步骤
Oct 18 Javascript
vue3.0 数字翻牌组件的使用方法详解
Apr 20 Vue.js
值得收藏的八个常用的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
优化使用mysql存储session的php代码
2008/01/10 PHP
PHP无敌近乎加密方式!
2010/07/17 PHP
php中使用ExcelFileParser处理excel获得数据(可作批量导入到数据库使用)
2010/08/21 PHP
PHP zip扩展Linux下安装过程分享
2014/05/05 PHP
Php连接及读取和写入mysql数据库的常用代码
2014/08/11 PHP
PHP过滤黑名单关键字的方法
2014/12/01 PHP
浅谈php冒泡排序
2014/12/30 PHP
php如何实现不借助IDE快速定位行数或者方法定义的文件和位置
2017/01/17 PHP
[原创]js与自动伸缩图片 自动缩小图片的多浏览器兼容的方法总结
2007/03/12 Javascript
javascript三元运算符用法实例
2015/04/16 Javascript
ECMAScript5(ES5)中bind方法使用小结
2015/05/07 Javascript
JavaScript中字面量与函数的基本使用知识
2015/10/20 Javascript
js点击文本框弹出可选择的checkbox复选框
2016/02/03 Javascript
很酷的星级评分系统原生JS实现
2016/08/25 Javascript
js document.getElementsByClassName的使用介绍与自定义函数
2016/11/25 Javascript
JS中使用cavas截图网页并解决跨域及模糊问题
2018/11/13 Javascript
JS使用cookie保存用户登录信息操作示例
2019/05/30 Javascript
移动端手指操控左右滑动的菜单
2019/09/08 Javascript
JavaScript实现动态留言板
2020/03/16 Javascript
《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析
2020/04/07 Javascript
Vue中keep-alive组件的深入理解
2020/08/23 Javascript
Python中用startswith()函数判断字符串开头的教程
2015/04/07 Python
python使用socket创建tcp服务器和客户端
2018/04/12 Python
numpy 进行数组拼接,分别在行和列上合并的实例
2018/05/08 Python
解决yum对python依赖版本问题
2019/07/05 Python
Python Django的安装配置教程图文详解
2019/07/17 Python
利用Python如何制作贪吃蛇及AI版贪吃蛇详解
2020/08/24 Python
4款Python 类型检查工具,你选择哪个呢?
2020/10/30 Python
HTML5未来发展趋势
2016/02/01 HTML / CSS
Html5实现文件异步上传功能
2017/05/19 HTML / CSS
英国领先的男装设计师服装独立零售商:Repertoire Fashion
2020/10/19 全球购物
幼儿园大班毕业感言
2014/02/06 职场文书
生物技术专业求职信
2014/06/10 职场文书
论文答辩开场白大全
2015/05/27 职场文书
蜗居观后感
2015/06/11 职场文书
Golang数据类型和相互转换
2022/04/12 Golang