提示输入框功能blur事件与click事件冲突解决

当搜索框失去焦点时会隐藏提示内容,导致点击提示词条无法正常触发事件。分析发现blur事件先于click事件执行。解决方案包括延迟blur事件执行和使用mousedown事件替换click事件,但都存在特定情况下的问题。在考虑兼容性和右键行为后,需找到更优解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

demo大概模样: 搜索框中输入关键字, 下方弹出提示, 点击提示词条, 去往相应的词条页面(这里用alert代替); 而搜索框失去焦点时, 会隐藏下方的提示内容
在这里插入图片描述
代码如下:

<body>
  <div class="container">
    <input type="text" id="input" placeholder="输入关键字" />
    <ul class="test" id="test">
      <li><a href="javascript:void(0)">西瓜</a></li>
      <li><a href="javascript:void(0)">苹果</a></li>
      <li><a href="javascript:void(0)">橙子</a></li>
      <li><a href="javascript:void(0)">甘蔗</a></li>
      <li><a href="javascript:void(0)">地瓜</a></li>
      <li><a href="javascript:void(0)">土豆</a></li>
      <li><a href="javascript:void(0)">山药</a></li>
      <li><a href="javascript:void(0)">葛根</a></li>
    </ul>
  </div>
  <script>
    var test = document.getElementById('test');
    var input = document.getElementById('input');
    var links = document.getElementsByTagName('a');
    input.onfocus = function () {
      test.style.display = 'block';
    }
    input.onblur = function () {
      test.style.display = 'none';
    }
    for (var i = 0; i < links.length; i++) {
      links[i].onclick = function() {
        alert(i); // do something
      }
    }
  </script>
</body>

点击词条, 并没有运行alert, 提示内容倒是隐藏了

原因分析:

搜索框的blur事件在a链接的click事件之前执行了, 结果是a链接的click事件压根没有触发


解决方案:

1. 首先想到的是延迟搜索框blur事件的执行

<body>
  <div class="container">
    <input type="text" id="input" placeholder="输入关键字" />
    <ul class="test" id="test">
      <li><a href="javascript:void(0)">西瓜</a></li>
      <li><a href="javascript:void(0)">苹果</a></li>
      <li><a href="javascript:void(0)">橙子</a></li>
      <li><a href="javascript:void(0)">甘蔗</a></li>
      <li><a href="javascript:void(0)">地瓜</a></li>
      <li><a href="javascript:void(0)">土豆</a></li>
      <li><a href="javascript:void(0)">山药</a></li>
      <li><a href="javascript:void(0)">葛根</a></li>
    </ul>
  </div>
  <script>
    var test = document.getElementById('test');
    var input = document.getElementById('input');
    var links = document.getElementsByTagName('a');
    input.onfocus = function () {
      test.style.display = 'block';
    }
    input.onblur = function () {
      setTimeout(() => {
        test.style.display = 'none';
      }, 100);
    }
    for (var i = 0; i < links.length; i++) {
      links[i].onclick = function() {
        alert(i); // do something
      }
    }
  </script>
</body>

这时看起来好像可以了, 但是有个问题, 一旦a链接的点击事件运行时间超过搜索框的blur事件的延迟时间, 比如这里设置的100ms, 就又不行了。 当然你可以设置延时长一点, 但如果场景要求不能延迟太长怎么办?

2. 将a链接的click事件, 换成mousedown事件

<body>
  <div class="container">
    <input type="text" id="input" placeholder="输入关键字" />
    <ul class="test" id="test">
      <li><a href="javascript:void(0)">西瓜</a></li>
      <li><a href="javascript:void(0)">苹果</a></li>
      <li><a href="javascript:void(0)">橙子</a></li>
      <li><a href="javascript:void(0)">甘蔗</a></li>
      <li><a href="javascript:void(0)">地瓜</a></li>
      <li><a href="javascript:void(0)">土豆</a></li>
      <li><a href="javascript:void(0)">山药</a></li>
      <li><a href="javascript:void(0)">葛根</a></li>
    </ul>
  </div>
  <script>
    var test = document.getElementById('test');
    var input = document.getElementById('input');
    var links = document.getElementsByTagName('a');
    input.onfocus = function () {
      test.style.display = 'block';
    }
    input.onblur = function () {
      test.style.display = 'none';
    }
    for (var i = 0; i < links.length; i++) {
      links[i].onmousedown = function() {
        alert(i); // do something
      }
    }
  </script>
</body>

因为blur事件的执行时机晚于mousedown, 所以可以愉快的alert了, 但是也还是有问题, 右键点击a链接, 也会执行mousedown, 当然, 如果你不介意右键行为, 可以就此打住了。但是如果场景要求在a链接上方右键时, 可以显示“在新标签页中打开链接”,像下面这样, 又该怎么办?
在这里插入图片描述


3.触发mousedown时, 判断是鼠标左键还是右键,左键则正常执行,右键时, 需要在blur事件执行前打断
<body>
  <div class="container">
    <input type="text" id="input" placeholder="输入关键字" />
    <ul class="test" id="test">
      <li><a href="javascript:void(0)">西瓜</a></li>
      <li><a href="javascript:void(0)">苹果</a></li>
      <li><a href="javascript:void(0)">橙子</a></li>
      <li><a href="javascript:void(0)">甘蔗</a></li>
      <li><a href="javascript:void(0)">地瓜</a></li>
      <li><a href="javascript:void(0)">土豆</a></li>
      <li><a href="javascript:void(0)">山药</a></li>
      <li><a href="javascript:void(0)">葛根</a></li>
    </ul>
  </div>
  <script>
    var test = document.getElementById('test');
    var input = document.getElementById('input');
    var links = document.getElementsByTagName('a');
    input.onfocus = function () {
      test.style.display = 'block';
    }
    input.onblur = function () {
      test.style.display = 'none';
    }
    for (var i = 0; i < links.length; i++) {
      links[i].onmousedown = function(e) {
        e = e || window.event;
        if (e.button === 0 || e.button === 1) { // 鼠标左键(ie8及以下button为1)
          alert(i); // do something
        } else if (e.button === 2) { // 鼠标右键
          if (e.preventDefault) {
            e.preventDefault();
          }
        }
      }
    }
  </script>
</body>

ok了, 这下在chrome浏览器中可以正常运行, 但是, 在ie8及以下, 右键时, 提示内容还是会隐藏, 无法达到预期的效果, 原因可能是 Event 对象的 cancelable 属性是 fasle, 没有默认动作,或者说不能阻止默认动作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值