You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中实现日期输入自动加斜杠?删除异常问题求助

React yyyy/mm/dd 日期输入框删除异常问题修复

你的代码在输入时能自动添加分隔符,但删除操作(尤其是从中间删除)会出现重复分隔符或格式混乱,核心原因是每次处理都直接清空所有非数字字符后重新拼接,没有考虑光标位置和删除操作的上下文,导致格式化逻辑和用户操作脱节。

以下是修复后的完整实现,同时优化了光标位置体验:

import { useState, useRef } from 'react';

function DOBInput() {
  const [dateOfBirth, setDateOfBirth] = useState("");
  const inputRef = useRef(null);

  const handleChangeDOB = (e) => {
    const { value, selectionStart } = e.target;
    const cursorPos = selectionStart;
    
    // 提取纯数字内容
    const numericValue = value.replace(/\D/g, "");
    let formatted = "";

    // 按规则拼接格式化字符串
    if (numericValue.length > 0) {
      formatted += numericValue.slice(0, 4);
      if (numericValue.length >= 5) {
        formatted += "/" + numericValue.slice(4, 6);
      }
      if (numericValue.length >= 7) {
        formatted += "/" + numericValue.slice(6, 8);
      }
    }

    // 计算光标位置偏移量,避免操作后光标跳转到末尾
    const originalSeparatorCount = (value.match(/\//g) || []).length;
    const newSeparatorCount = (formatted.match(/\//g) || []).length;
    let adjustedCursorPos = cursorPos;

    // 处理删除操作的光标调整
    if (value.length < dateOfBirth.length) {
      // 如果删除的是分隔符,光标位置回退一位
      if (value[cursorPos - 1] === "/") {
        adjustedCursorPos -= 1;
      }
      adjustedCursorPos += newSeparatorCount - originalSeparatorCount;
    } else {
      // 输入操作时,光标位置加上新增分隔符的数量
      adjustedCursorPos += newSeparatorCount - originalSeparatorCount;
    }

    setDateOfBirth(formatted);

    // 异步设置光标位置,确保DOM更新后生效
    setTimeout(() => {
      if (inputRef.current) {
        inputRef.current.setSelectionRange(adjustedCursorPos, adjustedCursorPos);
      }
    }, 0);
  };

  // 可选:失焦时验证日期合法性
  const validateDate = () => {
    const [year, month, day] = dateOfBirth.split("/").map(Number);
    if (!year || !month || !day) return false;
    const date = new Date(year, month - 1, day);
    return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day;
  };

  const handleBlur = () => {
    if (dateOfBirth && !validateDate()) {
      alert("请输入有效的日期格式");
      // 可选择清空输入或保留内容提示
      // setDateOfBirth("");
    }
  };

  return (
    <input
      ref={inputRef}
      type="text"
      maxLength={10}
      value={dateOfBirth}
      onChange={handleChangeDOB}
      onBlur={handleBlur}
      placeholder="yyyy/mm/dd"
    />
  );
}

export default DOBInput;

关键修复点:

  • 光标位置跟踪:使用useRef获取输入框DOM,操作后自动调整光标位置,避免每次输入/删除后光标跳转到末尾
  • 删除操作处理:区分输入和删除行为,针对删除分隔符的场景调整光标位置,防止格式错乱
  • 严格格式控制:只保留最多8位数字,拼接时严格按照yyyy/mm/dd的规则添加分隔符,避免多余符号

额外优化:

  • 新增失焦日期验证,确保输入的是合法日期
  • 变量名更符合React规范(dateOfBirth替代date_of_birth)

内容的提问来源于stack exchange,提问作者Anonymous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 20:34:53