本文详细解析了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事件。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。