js监听扫码枪

/**
 * @property {RegExp[]} patterns
 * @property {function(code:string):void} onScanSuccess
 */
class CodeScanner {

  /**
   * @param {(code:string)=>{}} handler
   * @param {RegExp[]} patterns
   */
  constructor(handler, patterns = []) {
    this.resetScan()
    this.patterns = patterns || []
    this.onScanSuccess = handler || ((code) => {
      console.log(code)
    })
  }

  /**
   * 开始监听
   */
  start() {
    this.resetScan()
    const that = this
    this.thatKeyHandler = (e) => {
      that._keyHandler(e)
    }
    document.addEventListener("keypress", this.thatKeyHandler, { passive: true })
  }

  /**
   * 停止接听
   */
  stop() {
    this.resetScan()
    document.removeEventListener("keypress", this.thatKeyHandler)
  }

  /**
   *
   * @param {KeyboardEvent} e
   * @private
   */
  _keyHandler(e) {
    if (["INPUT", "TEXTAREA", "BUTTON"].indexOf(document.activeElement.nodeName) >= 0) {
      return // 焦点在其它输入框时不触发
    }
    if (this.scanLastTimeStamp === 0) {
      this.code = e.key
      this.scanLastTimeStamp = e.timeStamp
      return
    }
    if (e.timeStamp - this.scanLastTimeStamp > 50) {
      return this.resetScan("超过扫描间隔的阈值(毫秒)")
    }
    if (e.key === "Enter") {
      let ok = this.patterns.length === 0
      for (let i = 0; i < this.patterns.length; i++) {
        if (this.code.match(this.patterns[i])) {
          ok = true
          break
        }
      }
      if (ok) {
        if (this.onScanSuccess !== null) {
          this.onScanSuccess(this.code)
        }
        return this.resetScan("正常结束扫描")
      } else {
        return this.resetScan("扫描码不符合规则")
      }
    }
    this.code += e.key
    this.scanLastTimeStamp = e.timeStamp
  }

  /**
   * @param {?string} reason
   */
  resetScan(reason = null) {
    if (reason) {
      console.log(reason,this.code)
    }
    this.scanLastTimeStamp = 0
    this.code = ""
  }
}

fyn