Next.js中点击输入框外部时如何让输入框失焦并隐藏搜索建议
你遇到的冲突本质是事件触发顺序问题:输入框的onBlur事件触发优先级高于建议项的click事件,onBlur执行后建议列表被直接销毁,绑定在列表元素上的跳转逻辑自然无法触发,以下是3种可直接落地的实现方案:
方案1:短延迟隐藏建议列表(改造成本最低)
给onBlur的隐藏逻辑加200ms左右的延迟,为建议项的点击事件预留执行时间,同时在onFocus时清理定时器避免状态冲突。
改造后代码:
import { useState, useRef } from 'react'; // 组件内新增定时器ref const hideTimerRef = useRef(null); const [suggestionState,setSuggestionState] = useState(false); <input type="input" ref={inputRef} autoFocus className={styles['search-bar-input']} onFocus={()=>{ // 先清掉待执行的隐藏逻辑 clearTimeout(hideTimerRef.current); setSuggestionState(true); }} onBlur={()=>{ // 延迟200ms执行隐藏 hideTimerRef.current = setTimeout(() => { setSuggestionState(false); }, 200); }} placeholder="Search Bloggo" onChange={(e)=>{ var trimmedQuery = e.target.value.trim(); setSearchQuery(trimmedQuery); getSuggestions(trimmedQuery); }} onKeyDown={(e)=>{handleKeypress(e)}} /> { searchQuery.length == 0 || suggestionState == false ? null : <div className={styles['search-bar-suggestions']}> <Link>... </Link> </div> }
方案2:判断失焦目标是否为建议列表元素(体验最优)
通过blur事件的relatedTarget属性判断新获得焦点的元素是否属于建议列表,如果是则不执行隐藏逻辑,完全没有延迟感知。
改造后代码:
import { useState, useRef } from 'react'; // 组件内新增建议列表ref const suggestionRef = useRef(null); const [suggestionState,setSuggestionState] = useState(false); <input type="input" ref={inputRef} autoFocus className={styles['search-bar-input']} onFocus={()=>{setSuggestionState(true)}} onBlur={(e)=>{ // 如果新聚焦的元素在建议列表内,不隐藏 if (suggestionRef.current?.contains(e.relatedTarget)) return; setSuggestionState(false); }} placeholder="Search Bloggo" onChange={(e)=>{ var trimmedQuery = e.target.value.trim(); setSearchQuery(trimmedQuery); getSuggestions(trimmedQuery); }} onKeyDown={(e)=>{handleKeypress(e)}} /> { searchQuery.length == 0 || suggestionState == false ? null : <div ref={suggestionRef} className={styles['search-bar-suggestions']}> <Link>... </Link> </div> }
方案3:阻止建议项点击时的输入框失焦行为
在建议项的mousedown事件中阻止默认行为,mousedown触发优先级高于blur,阻止默认行为后输入框不会失去焦点,也就不会触发隐藏逻辑,跳转执行完成后可手动关闭建议列表。
改造示例:
<div className={styles['search-bar-suggestions']}> <Link href="/xxx" onMouseDown={(e) => { // 阻止默认行为,避免输入框失焦 e.preventDefault(); // 跳转后手动隐藏建议列表,可选 setSuggestionState(false); }} > ... </Link> </div>
内容的提问来源于stack exchange,提问作者Aadhit Shanmugam
相关产品推荐
相关产品推荐

