点击Calendar组件图标时输入框失焦的问题解决咨询
解决输入框点击日历图标失焦的问题
问题背景
已实现功能:点击输入框时显示Calendar组件,点击输入框外部时隐藏该组件。
当前问题:点击Calendar组件内的图标时,输入框会失去焦点,导致Calendar组件被隐藏,无法正常操作日历功能。
解决方案
方法一:容器范围判断 + 事件冒泡阻止
核心思路是通过容器Ref判断点击区域是否属于输入框或Calendar组件,同时阻止图标点击事件的冒泡,避免触发不必要的失焦逻辑。
修改父组件代码
import { useState, useRef } from 'react'; // ...其他业务代码 const [isFocused, setIsFocused] = useState(false); // 获取输入框和Calendar的父容器Ref const inputContainerRef = useRef(null); const handleBlur = () => { // 延迟判断,确保点击事件先完成 setTimeout(() => { // 检查当前活跃元素是否在容器内,不在则隐藏Calendar if (!inputContainerRef.current?.contains(document.activeElement)) { setIsFocused(false); } }, 0); }; <form onSubmit={addTask}> <div ref={inputContainerRef}> <input id="task" placeholder=' Add task to "Inbox" on "Tomorrow"' className={styles.input} onChange={handleChange} value={taskName} onFocus={() => setIsFocused(true)} onBlur={handleBlur} ></input> {isFocused && <Calendar />} </div> </form>
修改Calendar组件代码
const Calendar = () => { const [isShown, setIsShown] = useState(false); const clickIcon = (e) => { e.preventDefault(); e.stopPropagation(); // 阻止事件冒泡,避免触发父元素的失焦相关逻辑 setIsShown((current) => !current); }; return ( <div> <CalendarMonthIcon onClick={clickIcon} className={styles.calendar} ></CalendarMonthIcon> {isShown && <Datepicker />} </div> ); };
方法二:Mousedown标记法
利用mousedown事件在blur之前触发的特性,设置标记忽略本次失焦。
修改父组件代码
const [isFocused, setIsFocused] = useState(false); // 标记是否忽略本次失焦 let ignoreBlur = false; const handleCalendarMousedown = () => { ignoreBlur = true; }; const handleBlur = () => { if (!ignoreBlur) { setIsFocused(false); } // 重置标记,不影响后续操作 ignoreBlur = false; }; <form onSubmit={addTask}> <div> <input id="task" placeholder=' Add task to "Inbox" on "Tomorrow"' className={styles.input} onChange={handleChange} value={taskName} onFocus={() => setIsFocused(true)} onBlur={handleBlur} ></input> {isFocused && <Calendar onMousedown={handleCalendarMousedown} />} </div> </form>
修改Calendar组件代码
const Calendar = ({ onMousedown }) => { const [isShown, setIsShown] = useState(false); const clickIcon = (e) => { e.preventDefault(); setIsShown((current) => !current); }; // 在Calendar容器上绑定mousedown事件,设置忽略失焦标记 return ( <div onMouseDown={onMousedown}> <CalendarMonthIcon onClick={clickIcon} className={styles.calendar} ></CalendarMonthIcon> {isShown && <Datepicker />} </div> ); };
内容的提问来源于stack exchange,提问作者aysh
相关产品推荐
相关产品推荐

