背景
在開發(fā)下拉選擇(picker)組件中遇到,點擊輸入框出現(xiàn)下拉列表,再點擊下拉列表選項后下拉列表自動收縮,然而選項值并沒有選到
一、blur和click事件簡述
- blur事件:當(dāng)元素失去焦點時觸發(fā)blur事件;其為表單事件,blur和focus事件不會冒泡,其他表單事件都可以。
- click事件:當(dāng)點擊元素時觸發(fā)click事件;所有元素都有此事件,會產(chǎn)生冒泡。
注(往往也是出現(xiàn)問題的原因): 點擊某元素導(dǎo)致前一個元素失去焦點,blur事件優(yōu)先于click事件
demo演示:
<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>
// 輸出結(jié)果:
my input blur
my button click
二、產(chǎn)生問題,blur與click沖突導(dǎo)致下拉值不能正常選值
實際開發(fā)中,我們會經(jīng)常遇到某一下拉列表框,點擊其他元素消失列表框;點擊下拉框子元素使其生效的需求。這就會面臨沖突問題。
demo演示:
<!-- DOM結(jié)構(gòu)示意 -->
<input type="text" placeholder="請選擇" readonly>
<div data-status="hide">
<ul>
<li><a href="javascript:">A</a></li>
<li><a href="javascript:">B</a></li>
<li><a href="javascript:">C</a></li>
<li><a href="javascript:">D</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");
});
// 選擇對應(yīng)選項,并賦值給input框
$(".search-list li a").click(function(){
console.log("執(zhí)行");
$("input").val($(this).text());
});
})(jQuery);
執(zhí)行demo,你會發(fā)現(xiàn),并不能正確獲取下拉框中某值。
這是為什么呢?:前文已知,blur優(yōu)先于click執(zhí)行,而JavaScript為單線程,同一時間只能執(zhí)行處理一個事件,這就導(dǎo)致blur事件優(yōu)先觸發(fā),隱藏了下拉框展示區(qū),所以導(dǎo)致其后續(xù)click事件并不會執(zhí)行。
三、解決方法
方法1:
用setTimeout對blur事件進(jìn)行延遲,讓click先執(zhí)行
//只提供關(guān)鍵代碼演示
$("input").focus(function(){
// input框獲取焦點,展示下拉框
$(".search-list").attr("data-status", "show");
}).blur(function(){
// input框失去焦點,隱藏下拉框
setTimeout(()=> { $(".search-list").attr("data-status", "hide");},500)
});
方法2:
使用mousedown代替click讓其優(yōu)先執(zhí)行
mousedown事件:當(dāng)鼠標(biāo)指針移動到元素上方,并按下鼠標(biāo)按鍵時,會發(fā)生mousedown事件。
mousedown事件優(yōu)先于click事件