在 JavaScript 中处理数字和日期输入的更好方法

valueAsNumber

你的代码可能像这样:

export function NumberInput() {
  const [number, setNumber] = useState(0)

  return (
    <input
      type="number"
      value={number}
      onChange={(e) => {
        const num = parseFloat(e.target.value)
        setNumber(num)
      }}
    />
  )
}

这很好,但实际上有一种更好的方法来读取数字值。

但是这个部分:

// 🚩 Unnecessary parsing!
const num = parseFloat(e.target.value)

但是从IE10时代开始,我们就有了更好的方法来获取和设置数字值:

// 🤯
const num = e.target.valueAsNumber

上述问题的更好解决方案可能是这样的:

export function NumberInput() {
  const [number, setNumber] = useState(0)

  return (
    <input
      type="number"
      value={number}
      onChange={(e) => {
        // ✅
        const num = e.target.valueAsNumber
        setNumber(num)
      }}
    />
  )
}

你同样可以查询一个 DOM 节点并使用它:

const myInput = document.querySelector('input.my-input')
const number = myInput.valueAsNumber

而且,重要的是,你也可以给它赋值

myInput.valueAsNumber = 123.456

一个小问题

valuseAsNumber的类型始终是数字。这意味着如果没有为输入设置当前值,你将得到NaN

typeof NaN // 'number'

是的,一个有趣的JavaScript 问题。因此,在将valueAsNumber写入需要实际数字的位置之前,一定要检查它是否为NaN

const number = myInput.valueAsNumber
if (!isNaN(number)) {
  // We actually have, like, a *number* number
}

valueAsDate

对于日期输入,我们还可以得到一个方便的valueAsDate属性:

export function DateInput() {
  const [date, setDate] = useState(null)

  return (
    <input
      type="date"
      value={date}
      onChange={(e) => {
        // ✅
        const date = e.target.valueAsDate
        setDate(date)
      }}
    />
  )
}

或者纯 JavaScript

const myDateInput = document.querySelector('input.my-date-input')
const date = myDateInput.valueAsDate

同样,也可以给它赋值:

myDateInput.valueAsDate = new Date(0)

这次没有陷阱

值得庆幸的是,对于valueAsDate,当输入为空时,我们得到的是null

const date = myDateInput.valueAsDate
if (date) {
  // We've got a date!
}

浏览器支持

即使这可能是你第一次了解这些属性,但它们已经存在多年了,甚至从IE 10的恐龙时代开始就存在了。