运行时参数数据类型校验工具类

工作所需进行工具封装,在此记录


import {
  isObject,
  isFunction,
  isString,
  isNumber,
  isArray,
  isBoolean,
} from '../xxx';
/**
 * 运行时参数数据类型校验工具类
 * @param {Object} data 源数据
 * @param {Object} rules 校验规则
 * @example
 * const data = { // 数据源
 *  phone: 1591231234,
 * };
 * const rules = { // 校验规则
 *  userInfo: {
 *    type: 'Object', // Any, Function, Object, Array, Boolean, Number, String
 *    require: true, // Boolean
 *    childNodes: { // 子节点 Object
 *      phone: {
 *        type: 'String',
 *        reg: /^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/, reg/string
 *      },
 *    },
 *  },
 * };
 * const validator = new Validator(data, rules) // 实例化校验器
 * validator.autoValidate(); // 自动根据rules校验data
 * validate.autoValidate(data, rules).validateString('tifa').validateArray(['', 1]); // 自定义链式调用
 */
class Validator {
  /**
   * validator
   * @param {Object} data 源数据
   * @param {Object} rules 校验规则
   */
  constructor(data, rules) {
    this._rules = rules;
    this.data = data;
  }

  _typeMap = {
    'Any': 'Any',
    '[object Function]': 'Function',
    '[object Object]': 'Object',
    '[object Array]': 'Array',
    '[object Boolean]': 'Boolean',
    '[object Number]': 'Number',
    '[object String]': 'String',
  }

  /**
   * js原生类型_typeMap映射
   * @param {any} data 原始数据
   * @returns {String} _typeMap
   */
  getType(data = this.data) {
    const acceptOriginType = Object.prototype.toString.call(data)
    return this._typeMap[acceptOriginType];
  }

  /**
   * 
   * @param {Object} data 校验目标对象
   * @param {Object} rules 校验规则
   * @returns {validator} 校验器实例
   */
  normalValidate(data = this.data, rules = this._rules) {
    const dataType = this.getType(data);
    if (dataType !== 'Object') {
      this._errorHandler(`应为Object,但接收到${dataType}`)
    }

    const source = {
      keyList: Object.keys(data),
      valueList: Object.values,
    };

    Object.entries(rules).map(([filedName, filedRule]) => {
      const {
        type = 'Any',
        require = false,
        range,
        childNodes,
        reg,
      } = filedRule;

      // 必传字段
      if (require && !source.keyList.includes(filedName)) {
        this._errorHandler(`${filedName}为必传参数,当前参数${source.keyList}`)
      }

      // 当前规则校验的字段
      const sourceValue = data[filedName];
      const sourceValueType = this.getType(sourceValue);
      if (sourceValue !== undefined && sourceValue !== 'undefined') {
        // 类型校验
        if (type !== sourceValueType && type !== 'Any') {
          this._errorHandler(`${filedName}参数应为${type},但接收到${sourceValue}=> ${sourceValueType}`)
        }

        const r = new RegExp(reg);
        if (reg && !r.test(`${sourceValue}`)) {
          this._errorHandler(`${filedName}参数应符合${reg}规则,但接收到${sourceValue}=> ${sourceValueType}`)
        }

        // 入参取值范围限制
        if (range && range.length) {
          const rangeLimit = range.some(item => !['String', 'Number'].includes(this.getType(item)))
          if (rangeLimit) this._errorHandler('range只接受String/Number')
          if (!range.includes(sourceValue)) this._errorHandler(`${filedName}的值只能在${range}中选择`)
        }

        const childNodesType = this.getType(childNodes);

        // 节点校验器limit
        if (childNodes && childNodesType !== 'Object') {
          this._errorHandler(`childNodes应为Object,但接收到${childNodesType}`)
        }

        // 子节点校验器存在,递归校验子节点
        if (childNodes) {
          this.normalValidate(sourceValue, childNodes)
        }
      }
    })
    return this;
  }

  /**
   * 校验对象类型
   * @returns {validator} 校验器实例
   */
  validateObject(data = this.data) {
    const result = isObject(data);
    if (!result) this._errorHandler(`参数错误,应为Object,但接收到${this.getType(data)}`);
    return this;
  }

  /**
   * 校验函数类型
   * @returns {validator} 校验器实例
   */
  validateFunction(data = this.data) {
    const result = isFunction(data);
    if (!result) this._errorHandler(`参数错误,应为Function,但接收到${this.getType(data)}`);
    return this;
  }

  /**
   * 校验字符串类型
   * @param {Any} data 原始数据
   * @returns {validator} 校验器实例
   */
  validateString(data = this.data) {
    const result = isString(data);
    if (!result) this._errorHandler(`参数错误,应为String,但接收到${this.getType(data)}`);
    return this;
  }

  /**
   * 校验数字类型
   * @param {Any} data 原始数据
   * @returns {validator} 校验器实例
   */
  validateNumber(data = this.data) {
    const result = isNumber(data)
    if (!result) this._errorHandler(`参数错误,应为Number,但接收到${this.getType(data)}`);
    return this;
  }

  /**
   * 校验数组类型
   * @param {Any} data 原始数据
   * @returns {validator} 校验器实例
   */
  validateArray(data = this.data) {
    const result = isArray(data);
    if (!result) this._errorHandler(`参数错误,应为Array,但接收到${this.getType(data)}`);
    return this;
  }

  /**
   * 校验布尔类型
   * @param {Any} data 原始数据
   * @returns {validator} 校验器实例
   */
  validateBoolean(data = this.data) {
    const result = isBoolean(data);
    if (!result) this._errorHandler(`参数错误,应为Boolean,但接收到${this.getType(data)}`);
    return this;
  }

  /**
   * 兼容function转string,仅用于提示性转换
   * @param {any} data 原始数据
   * @returns {String} 返回字符串
   */
  _dataToString(data) {
    const type = this.getType(data)
    return type === 'Function' ? data : JSON.stringify(data)
  }

  _errorHandler(msg) {
    throw new Error(`参数错误!${msg}`)
  }
}

export default Validator;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用Qt的UI界面设计串口数据采集,主要分为以下几个步骤: 1. 打开串口:通过Qt提供的QSerialPort类,可以很方便地实现串口的打开,设置波特率、数据位、校验位等参数。 2. 接收数据:通过QSerialPort的信号readyRead(),可以实现串口数据的接收。在该信号的槽函数中,可以读取串口缓冲区中的数据,并进行处理。 3. 数据处理:对于接收到的串口数据,可以根据具体需求进行处理,例如解析数据、显示数据等。可以使用Qt提供的控件(如QLabel、QTextEdit)来显示数据。 4. 发送数据:如果需要向串口发送数据,可以通过QSerialPort的write()函数来实现。可以在UI界面上添加一个发送按钮,通过点击按钮来发送数据。 5. 关闭串口:在程序退出或不需要使用串口时,需要关闭串口以释放资源。可以在UI界面上添加一个关闭串口的按钮,点击该按钮触发关闭串口的操作。 在UI界面设计上,可以使用Qt Designer工具来创建串口数据采集的界面。可以设计一个包含打开串口按钮、发送按钮、接收区域等控件的界面。通过设置控件的属性、信号与槽的连接,实现与串口通信相关的功能。 总结来说,使用Qt的UI界面设计串口数据采集需要先打开串口,接收并处理串口数据,同时可以发送串口数据,最后关闭串口以释放资源。设计上可以使用Qt Designer工具创建界面,通过设置控件属性和信号与槽的连接来实现功能。 ### 回答2: 在Qt中设计串口数据采集的UI界面可以通过以下步骤实现: 首先,通过Qt Creator创建一个新的Qt项目,并选择“MainWindow”作为主窗口类型。 接下来,在UI界面中添加所需的控件,可以包括一个按钮来打开或关闭串口,一个下拉菜单用于选择串口波特率,一个文本框来显示串口接收到的数据等。 然后,在主窗口类中添加相关的槽函数来处理控件的事件响应。比如,添加一个槽函数来处理打开或关闭串口的按钮点击事件,可以使用Qt提供的串口类(QSerialPort)来实现串口的打开和关闭操作。在打开串口时,需要设置串口的波特率以及其他参数,如数据位、停止位和校验位等。 接着,在主窗口类的构造函数中初始化串口类实例,并连接相关的信号和槽函数。比如,连接串口的readyRead()信号与一个槽函数,用于读取串口接收到的数据,并在文本框中显示出来。 最后,在UI界面的其他控件事件响应函数中,可以添加一些额外的逻辑来实现串口数据的采集,如将接收到的数据保存到文件中、进行数据处理或显示等。 需要注意的是,由于串口数据读取是一个耗时操作,为了避免界面卡顿,可以将串口读取相关的逻辑放在一个单独的线程中运行,然后通过信号和槽机制与主界面进行通信。可以使用Qt提供的多线程类(QThread)来实现。 综上所述,通过以上步骤可以实现使用Qt的UI界面设计串口数据采集的功能。这样设计的界面用户可以方便地打开/关闭串口,选择波特率,实时显示串口接收到的数据,并且可以进行数据采集以及其他操作。 ### 回答3: 在使用Qt进行串口数据采集的UI界面设计时,首先需要使用Qt提供的QSerialPort类来实现串口的打开、读写、关闭等操作。 在UI界面设计方面,可以使用Qt的图形设计工具Qt Designer来创建界面,或者手动编写代码实现。以下是一个简单的示例: 1. 首先,在Qt Designer中创建一个主窗口界面,并添加串口设置相关的控件,如按钮、下拉框、文本框等。可以设置按钮用来打开串口、读取数据等操作。 2. 在主窗口的类文件中,需要引入QSerialPort类的头文件,以及其它相关的Qt类文件。 3. 在打开串口的按钮点击事件中,实例化QSerialPort对象,并设置串口的名称、波特率、数据位、校验位和停止位等参数。然后,调用QSerialPort的open函数打开串口。 4. 在循环读取数据的函数中,通过QSerialPort的read函数读取串口接收到的数据,并将数据显示在相应的文本框中或者进行其它业务逻辑处理。 5. 最后,在关闭串口的槽函数中,调用QSerialPort的close函数关闭串口。 通过以上步骤,可以设计一个简单的Qt界面,用于串口数据的采集。当用户点击相应按钮时,可以打开串口、读取数据,并在界面上显示或者进行进一步处理。在设计时,还可以添加错误处理、自动刷新等功能,以提高用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值