You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止点击搜索列表项时触发输入框的onBlur事件?

解决搜索输入框失焦(blur)优先于列表项点击(click)触发的问题

问题原因

blur 事件的触发优先级高于 click,而且 stopPropagation() 无法改变这个顺序——因为两者不属于同一事件流,blur 是焦点事件,click 是鼠标事件,前者会在后者之前触发。所以点击列表项时,输入框先失焦隐藏列表,导致 click 事件无法被触发。

解决方案

1. 用 setTimeout 延迟执行失焦逻辑

给 onBlur 里的隐藏逻辑加一个短暂延迟,让 click 事件有足够时间执行:

<Container className='search-widget'>
  <div className={field-wrapper}>
    <SearchField
      onFocus={() => { /* 显示匹配列表的逻辑 */ }}
      onBlur={() => {
        // 延迟100ms执行失焦后的隐藏操作
        setTimeout(() => {
          console.log('onBlur')
          // 这里写入隐藏列表的逻辑
        }, 100)
      }}
    />
    <Button onClick={...}>
      <img src='/images/Search/search.svg' alt='search' />
    </Button>
  </div>
  <SearchList
    itemOnClick={data => {
      console.log('onClick')
      // 列表项点击后的业务逻辑(如填充输入框、跳转等)
    }}
  />
</Container>

优点:实现简单,无需大幅修改现有代码;缺点:存在轻微延迟感,部分场景下可能影响体验。

2. 用 mousedown 替代 click 处理列表项操作

mousedown 事件的触发时机早于 blur,可以借助这个特性先执行列表项的操作,再通过标志位控制 blur 是否执行:

// 在组件内部定义一个标志位
let isItemClicking = false;

<Container className='search-widget'>
  <div className={field-wrapper}>
    <SearchField
      onFocus={() => { /* 显示匹配列表的逻辑 */ }}
      onBlur={() => {
        if (!isItemClicking) {
          console.log('onBlur')
          // 这里写入隐藏列表的逻辑
        }
        // 重置标志位
        isItemClicking = false;
      }}
    />
    <Button onClick={...}>
      <img src='/images/Search/search.svg' alt='search' />
    </Button>
  </div>
  <SearchList
    // 给列表项绑定 mousedown 事件
    itemOnMouseDown={(data) => {
      isItemClicking = true;
      console.log('执行列表项操作', data)
      // 这里写入列表项点击后的业务逻辑
    }}
    // 保留 click 事件兼容其他场景(如键盘触发)
    itemOnClick={data => {
      console.log('onClick')
    }}
  />
</Container>

优点:无延迟,逻辑精准;缺点:需要额外处理鼠标事件与键盘事件的兼容。

3. 将输入框与列表放入同一焦点容器

给外层容器添加 tabIndex,让容器成为焦点载体,点击列表时容器不会失焦,从而避免输入框触发 blur:

<Container 
  className='search-widget'
  tabIndex="-1"
  onFocus={() => { /* 显示匹配列表的逻辑 */ }}
  onBlur={() => { 
    console.log('容器失焦')
    // 这里写入隐藏列表的逻辑
  }}
>
  <div className={field-wrapper}>
    <SearchField />
    <Button onClick={...}>
      <img src='/images/Search/search.svg' alt='search' />
    </Button>
  </div>
  <SearchList
    itemOnClick={data => {
      console.log('onClick')
      // 列表项点击后的业务逻辑
    }}
  />
</Container>

优点:从根源上解决焦点问题,无额外延迟;缺点:需要调整焦点管理逻辑,确保容器能正确获取/失去焦点。


内容的提问来源于stack exchange,提问作者Джамбулат Кагерманов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 23:22:25