如何处理输入框聚焦状态下内部按钮的交互问题?
解决密码输入框焦点与显示按钮的交互问题
这个问题的核心是点击按钮时输入框失去焦点,触发onBlur隐藏按钮,导致交互中断。下面提供几种可行的解决方法:
方法1:通过onBlur的relatedTarget判断焦点是否在内部
利用blur事件的relatedTarget属性,判断焦点是否转移到了同一个容器内的按钮上。只有当焦点完全离开整个输入容器时,才隐藏按钮。
修改后的代码:
<div className="input-wrapper"> <input onFocus={() => setShowButton(true)} onBlur={(e) => { // 检查焦点是否转移到了容器内的按钮 const isFocusingInside = e.currentTarget.closest('.input-wrapper').contains(e.relatedTarget); if (!isFocusingInside) { setShowButton(false); } }} title="password" type={type === 'password' && toggle ? 'text' : 'password'} {...props} /> {showButton && ( <button type="button" className={type === 'password' ? 'password' : ''} onClick={() => setToggle(!toggle)} > {toggle ? <ShowPasswordIcon /> : <HidePasswordIcon />} </button> )} </div>
方法2:阻止按钮mousedown的默认行为
mousedown事件会在blur之前触发,阻止它的默认行为可以避免输入框失去焦点。这样点击按钮时,输入框保持焦点,按钮不会消失。
修改按钮部分:
<button type="button" className={type === 'password' ? 'password' : ''} onMouseDown={(e) => e.preventDefault()} // 阻止默认焦点转移 onClick={() => setToggle(!toggle)} > {toggle ? <ShowPasswordIcon /> : <HidePasswordIcon />} </button>
方法3:用CSS :focus-within替代JS状态(更简洁)
不需要依赖React状态,直接通过CSS的:focus-within伪类控制按钮显示。只要容器内的输入框或按钮有焦点,按钮就会显示。
首先移除JS中的onFocus、onBlur和showButton状态:
<div className="input-wrapper"> <input title="password" type={type === 'password' && toggle ? 'text' : 'password'} {...props} /> <button type="button" className={`${type === 'password' ? 'password' : ''}`} onClick={() => setToggle(!toggle)} > {toggle ? <ShowPasswordIcon /> : <HidePasswordIcon />} </button> </div>
然后添加CSS:
.input-wrapper .password { display: none; /* 默认隐藏按钮 */ } .input-wrapper:focus-within .password { display: inline-block; /* 容器内有焦点时显示按钮 */ }
这种方法更符合原生交互逻辑,减少JS状态管理。
内容的提问来源于stack exchange,提问作者Jeluxe
相关产品推荐
相关产品推荐

