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
相关产品推荐
相关产品推荐

