JavaScript中blur与click事件冲突的两种解决方案

作者:像素猫

时间:2026-10-21

浏览:211

本文针对JavaScript开发中常见的下拉框blur与click事件冲突问题,深入分析了事件触发顺序及单线程执行机制。通过两个实际案例,分别提供了使用setTimeout延迟blur执行和将click替换为mousedown两种解决方案,确保下拉选项能正确选中并赋值。

文章目录

解决blur与click冲突

解决blur与click冲突

前言:

在前端开发过程中,blur和click事件的冲突是一个高频出现的难题。本文将通过一个典型的“下拉框”应用场景,详细阐述该问题,并提供两种行之有效的解决思路。

blur和click事件简述

一、blur和click事件简述

  1. blur事件:当元素失去焦点时触发。它属于表单事件,值得注意的是,blur和focus事件不会发生冒泡,而其他大多数表单事件是可以冒泡的。
  2. click事件:当用户点击元素时触发。该事件适用于所有元素,并且会产生冒泡现象。

示例1:blur事件为表单事件


<input type="text" id="tel">
<script>
  document.addEventListener("blur", function(){
    console.log("my document blur");
  });

  var ipt = document.getElementById("tel");
  ipt.addEventListener("blur", function(){
    console.log("my input blur");
  });
</script>
// 输出结果:document为非表单元素
my input blur

示例2:click事件可冒泡


<input type="text" id="tel">
<script>
  document.addEventListener("click", function(){
    console.log("my document click");
  });

  var ipt = document.getElementById("tel");
  ipt.addEventListener("click", function(){
    console.log("my input click");
  });
</script>
// 输出结果:
my input click
my document click

示例3:点击某元素导致前一个元素失去焦点,blur事件优先于click事件


<input type="text" id="ipt">
<input type="button" id="btn" value="点我">
<script>
  var ipt = document.getElementById("ipt");
  ipt.addEventListener("blur", function(){
    console.log("my input blur");
  });

  var btn = document.getElementById("btn");
  btn.addEventListener("click", function(){
    console.log("my button click");
  });
</script>
// 输出结果:
my input blur
my button click

下拉框blur和click事件冲突,导致不能正常选择值

二、下拉框blur和click事件冲突,导致不能正常选择值

在实际业务场景中,我们常需实现这样的交互:点击输入框时显示下拉列表,点击列表外区域时隐藏列表,而点击列表内的子元素则选中该项。这种需求往往会导致事件冲突。


<!-- DOM结构示意 -->
<input type="text" placeholder="请选择姓氏" readonly>
<div class="search-list" data-status="hide">
  <ul>
    <li><a href="javascript:">赵</a></li>
    <li><a href="javascript:">钱</a></li>
    <li><a href="javascript:">孙</a></li>
    <li><a href="javascript:">李</a></li>
  </ul>
</div>

/** 说明:
 * 目前通过ul外层div自定义属性“data-status”控制其是否显示  
 */
(function($){
  $("input").focus(function(){
    // input框获取焦点,展示下拉框
    $(".search-list").attr("data-status", "show");
  }).blur(function(){
    // input框失去焦点,隐藏下拉框
    $(".search-list").attr("data-status", "hide");
  });
  // 选择对应选项,并赋值给input框
  $(".search-list li a").click(function(){
    console.log("执行");
    $("input").val($(this).text());
  });
})(jQuery);

若直接执行上述代码,会发现无法正确获取下拉框中的值。

原因分析:JavaScript是单线程模型,同一时刻只能处理一个事件。结合示例3可知,“blur优先于click执行”。在本例中,blur处理程序会立即隐藏下拉展示区,导致后续的click事件无法在目标元素上正常触发,因此console日志也不会输出。

解决方案1:对blur事件进行延迟,让click先执行。


(function($){
  $("input").focus(function(){
    // input框获取焦点,展示下拉框
    $(".search-list").attr("data-status", "show");
  }).blur(function(){
    setTimeout(function(){
      // input框失去焦点,隐藏下拉框
      $(".search-list").attr("data-status", "hide");
    }, 300);
  });
  // 选择对应选项,并赋值给input框
  $(".search-list li a").click(function(){
    console.log("执行");
    $("input").val($(this).text());
  });
})(jQuery);

使用mousedown让其优先执行

三、使用mousedown让其优先执行

示例4:将示例3中的click事件改为mousedown


<input type="text" id="ipt">
<input type="button" id="btn" value="点我">
<script>
  var ipt = document.getElementById("ipt");
  ipt.addEventListener("blur", function(){
    console.log("my input blur");
  });

  var btn = document.getElementById("btn");
  btn.addEventListener("mousedown", function(){
    console.log("my button mousedown");
  });
</script>
// 输出结果:
my button mousedown
my input blur

mousedown事件:当鼠标指针移动到元素上方并按下鼠标按键时触发。

mouseup事件:当在元素上松开鼠标按钮时触发。

注意:

(1)mousedown 与 click 事件不同,mousedown 事件仅需要按键被按下,而不需要松开即可发生。 (2)mouseup 与 click 事件不同,mouseup 事件仅需要放松按钮。当鼠标指针位于元素上方时,放松鼠标按钮就会触发该事件。

补充:mousedown、mouseup、click



<input type="button" id="btn" value="点我">
var btn = document.getElementById("btn");
btn.addEventListener("mousedown", function(){
  console.log("my button mousedown");
});
btn.addEventListener("click", function(){
  console.log("my button click");
});
btn.addEventListener("mouseup", function(){
  console.log("my button mouseup");
});
输出结果:
my button mousedown
my button mouseup
my button click

因此,其执行顺序为:

mousedown >> mouseup >> click

解决方案2:将click事件改为mousedown,让其优先于blur事件执行


(function($){
  $("input").focus(function(){
    // input框获取焦点,展示下拉框
    $(".search-list").attr("data-status", "show");
  }).blur(function(){
    // input框失去焦点,隐藏下拉框
    $(".search-list").attr("data-status", "hide");
  });
  // 选择对应选项,并赋值给input框
  $(".search-list li a").mousedown(function(){
    $("input").val($(this).text());
  });
})(jQuery);

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章