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

React实现text输入框输入时部分保留placeholder占位符效果

React实现输入时保留部分占位符的DD-MM-YYYY日期输入框

不要尝试直接通过修改input的placeholder属性或者伪元素样式实现这个效果,原生DOM没有提供拆分placeholder内容的能力,所有直接操作原生placeholder的方案都无法满足部分保留的需求。要实现输入时只移除已输入位置的占位符、剩余占位符常驻的效果,叠层方案是兼容性最好、体验最接近原生输入的选择,核心逻辑是把真实输入框和占位符展示层完全对齐叠加,根据输入长度动态展示剩余的占位符内容。

核心实现逻辑

  • 用相对定位容器包裹两个绝对定位的子元素:上层是透明的真实输入框(只保留光标可见),下层是占位符展示层,负责展示已输入内容+剩余占位符
  • 监听输入事件,过滤非数字内容,可选择自动补充分隔符-减少用户手动输入成本
  • 根据当前输入值的长度,截取原始占位符DD-MM-YYYY对应长度之后的内容作为剩余展示部分
  • 保证点击、输入、删除、选中文本的交互和普通输入框完全一致,聚焦态边框样式同步

完整实现代码

组件代码

import { useState } from 'react';
import './DateInput.css';

const PartialPlaceholderDateInput = () => {
  const [inputValue, setInputValue] = useState('');
  const FULL_PLACEHOLDER = 'DD-MM-YYYY';

  const handleInputChange = (e) => {
    // 过滤所有非数字输入
    const rawNum = e.target.value.replace(/[^0-9]/g, '');
    let formatted = '';

    // 按DD-MM-YYYY格式自动补充分隔符,不需要自动补可以去掉这段逻辑直接用rawNum
    if (rawNum.length > 0) {
      // 拼接日部分,最多2位
      formatted += rawNum.slice(0, 2);
      if (rawNum.length >= 3) {
        formatted += '-';
        // 拼接月部分,最多2位
        formatted += rawNum.slice(2, 4);
        if (rawNum.length >= 5) {
          formatted += '-';
          // 拼接年部分,最多4位
          formatted += rawNum.slice(4, 8);
        }
      }
    }

    // 超过完整日期长度就不再更新
    if (formatted.length > 10) return;
    setInputValue(formatted);
  };

  // 截取未输入部分的占位符
  const restPlaceholder = FULL_PLACEHOLDER.slice(inputValue.length);

  return (
    <div className="date-input-wrap">
      {/* 真实输入框,叠加在最上层 */}
      <input
        type="text"
        value={inputValue}
        onInput={handleInputChange}
        className="real-date-input"
        maxLength={10}
      />
      {/* 占位符展示层,在输入框下方 */}
      <div className="placeholder-show-layer">
        <span className="inputted-content">{inputValue}</span>
        <span className="rest-placeholder">{restPlaceholder}</span>
      </div>
    </div>
  );
};

export default PartialPlaceholderDateInput;

样式代码(DateInput.css)

.date-input-wrap {
  position: relative;
  width: 150px;
  height: 34px;
  font-size: 14px;
}

.real-date-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding: 0 10px;
  box-sizing: border-box;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  font-size: 14px;
  color: transparent; /* 输入文字透明,显示下层的内容即可 */
  caret-color: #303133; /* 保留输入光标为正常颜色 */
  background: transparent;
  z-index: 1;
}

.real-date-input:focus {
  outline: none;
  border-color: #409eff;
}

.placeholder-show-layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding: 0 10px;
  line-height: 34px;
  box-sizing: border-box;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  pointer-events: none; /* 事件穿透,不影响输入框点击 */
}

/* 已输入内容用正常文字颜色 */
.inputted-content {
  color: #303133;
}

/* 剩余占位符用浅灰色 */
.rest-placeholder {
  color: #c0c4cc;
}

/* 输入框聚焦时,占位符层边框同步高亮 */
.real-date-input:focus + .placeholder-show-layer {
  border-color: #409eff;
}

效果说明

  • 未输入时完整显示DD-MM-YYYY浅灰色占位符
  • 输入2位数字后,自动补上-,占位符剩余-MM-YYYY,整体展示为02-MM-YYYY的效果
  • 输入4位数字(日+月)后自动补上第二个-,占位符剩余-YYYY
  • 输入满8位数字后自动生成完整DD-MM-YYYY格式日期,占位符完全消失
  • 退格删除时会自动移除多余的分隔符,占位符随输入长度减少逐步恢复显示

如果不需要自动补分隔符的能力,只需要去掉handleInputChange里拼接-的逻辑,直接保存过滤后的数字值即可,占位符截断的逻辑完全不需要修改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 07:45:29