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

作者:小圆点时间:2026-10-30 15:09:24浏览:459

本文详细解析了JavaScript中下拉框开发时blur与click事件冲突的问题。由于JS单线程机制,blur优先于click执行导致选择失效。文章提供了两种解决方案:一是利用setTimeout对blur进行延迟,确保click先执行;二是将click替换为mousedown事件,利用其执行顺序早于blur的特性,从而正确获取下拉值。

引言

在Web开发过程中,开发者经常需要处理blur和click事件之间的冲突。本文将针对下拉框这一常见场景,深入分析冲突产生的原因,并提供两种切实可行的解决方案。

blur和click事件简述

一、blur和click事件简述

blur事件属于表单事件,当元素失去焦点时触发。值得注意的是,blur和focus事件不会冒泡,而其他的表单事件通常可以冒泡。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事件无法被执行,因此控制台也不会输出相关信息。

解决方案一:延迟blur事件

解决方案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事件不同,它仅需按键被按下即可触发,无需松开。 (2)mouseup与click事件不同,它仅在鼠标指针位于元素上方时松开按钮即可触发。

补充: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);

补充:表单验证中的冲突处理

补充: js、jquery 中 blur事件和click事件冲突

问题说明: 在表单验证场景中,通常会在输入框失去焦点时触发blur事件。然而,当失去焦点后点击按钮时,blur和click事件会被同时触发。由于JavaScript的单线程特性,这会导致执行顺序问题。此时需要确保blur事件先执行验证逻辑,随后再触发click事件。

解决方法:

给按钮的click事件设置延迟执行setTimeOut(fn,100),延迟时间的设置要大于blur事件的执行时间,这样就会在blur事件执行完后在执行click事件。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章