如何仅在目标元素未处于当前聚焦状态时对其执行focus操作?
问题根因
你遇到的判断失效、输入框重复聚焦的核心原因是DOM事件的触发顺序:mousedown → 浏览器默认修改activeElement → mouseup → click。点击图标时,mousedown阶段浏览器检测到图标不属于可聚焦元素,会先把当前焦点转移到body,等执行click事件内的判断逻辑时,document.activeElement已经被修改为body,所以判断条件永远成立,导致输入框被重复聚焦,触发不必要的过渡动画。
最简解决方案
不需要引入额外状态和副作用,直接把图标绑定的onClick事件替换为onMouseDown,同时阻止浏览器默认的焦点转移行为即可:
onMouseDown={(e) => { // 阻止默认行为,避免activeElement被自动修改为body e.preventDefault(); if (document.activeElement !== inputEl.current) { inputEl.current.focus(); } }}
这个方案不会出现先失焦再聚焦的情况,过渡动画仅会在输入框首次聚焦时触发,符合你的需求。
状态方案可行性说明
你设想的用状态记录聚焦状态、useEffect监听失焦重置的方案是可运行的,但属于非必要的复杂实现:需要额外引入状态依赖,还要手动绑定、清理聚焦/失焦监听事件,维护成本更高,也存在状态同步异常的潜在风险,除非有特殊场景必须使用click事件,否则不优先推荐。如果确实需要用该方案,参考实现如下:
const [isInputFocused, setIsInputFocused] = useState(false); useEffect(() => { const input = inputEl.current; if (!input) return; const handleFocus = () => setIsInputFocused(true); const handleBlur = () => setIsInputFocused(false); input.addEventListener('focus', handleFocus); input.addEventListener('blur', handleBlur); return () => { input.removeEventListener('focus', handleFocus); input.removeEventListener('blur', handleBlur); }; }, []); onClick={() => { if (!isInputFocused) { inputEl.current.focus(); } }}
内容的提问来源于stack exchange,提问作者embracethefuture
相关产品推荐
相关产品推荐

