在本例中,我们将强制用户只输入给定集合中的字符。具体来说,本演示中支持的字符包括数字和空格。

以下是一个基本的 input 元素:

<input type="text" id="input" />

处理事件

通过处理 keypress 事件,我们可以防止用户输入数字和空格以外的字符:

const ele = document.getElementById('input')

ele.addEventListener('keypress', function (e) {
  // 获取按键代码
  const key = e.which || e.keyCode

  // 0, 1, ..., 9 的键码分别为 48, 49, ..., 57
  // 空格键码为 32
  if (key != 32 && (key < 48 || key > 57)) {
    // 防止默认动作
    e.preventDefault()
  }
})

它看起来不错,但还不够,因为用户仍然可以将不支持的字符粘贴或拖动到输入中。这些情况可由 input 事件处理:

// 跟踪当前值
let currentValue = ele.value || ''

ele.addEventListener('input', function (e) {
  const target = e.target

  // 如果用户输入支持的字符(数字或空格)
  /^[0-9\s]*$/.test(target.value)
    ? (currentValue = target.value) // 备份当前值 
    : (target.value = currentValue) // 否则,恢复值 
    // 请注意,在这种情况下,e.preventDefault() 没有帮助
})

这里我们检查该值是否与包含数字和空格字符的正则表达式 /^[0-9\s]*$/ 匹配。

它修复了用户从键盘 (Ctrl + V)、上下文菜单或下拉文本粘贴到输入的情况。

但还有另一个问题。调用 target.value = currentValue 会将光标放在输入的末尾。我们必须保持光标的位置。

// 跟踪当前光标的位置
const selection = {}

ele.addEventListener('keydown', function (e) {
  const target = e.target
  selection = {
    selectionStart: target.selectionStart,
    selectionEnd: target.selectionEnd
  }
})

当用户更改输入值时,如果该值不受支持,我们将恢复值和所选的位置:

ele.addEventListener('input', function (e) {
  const target = e.target

  if (/^[0-9\s]*$/.test(target.value)) {
    currentValue = target.value
  } else {
    // 用户输入不支持的字符,恢复值和所选内容
    target.value = currentValue
    target.setSelectionRange(selection.selectionStart, selection.selectionEnd)
  }
})

正如您在最后的演示中看到的那样,我们可以将跟踪的属性(valueselectionStartselectionEnd)组合到一个变量中。

查看效果

使用特殊 input 类型

我们可以使用特殊的 HTML 5 input 类型来服务特定的用例:

INPUT 描述
<input type="color" /> 让用户指定颜色
<input type="date" /> 让用户输入日期
<input type="email" /> 让用户输入电子邮件地址
<input type="number" /> 只允许用户输入数字
<input type="tel" /> 让用户输入电话号码
<input type="time" /> 让用户输入时间
<input type="url" /> 让用户输入 URL

您可以在此处查看更多内置类型。

这里注意一下,本示例不能使用 <input type="number" />,因为它不允许输入空格。