无需全局焦点追踪,输入框blur时如何获取当前获焦元素ID?
问题描述
我需要知道当某个特定输入框失去焦点(blur)时,哪个对象获得了焦点(focus)。能通过blur函数判断输入框何时失焦,但拿不到当前获焦对象的ID。
具体场景是:某个输入框获焦时会执行特定操作,我要判断用户点击切换到其他输入框时,停止该操作。
示例代码:
<input id="field1"> <input id="field2">
$("#field2").on("blur", function() { if $(":hasfocus").id() === "field1" { // do something } });
尝试过程中遇到的问题:
- blur事件没法直接满足需求,我明确要知道当前获焦对象的ID;
- 试过用
:focus选择器,但没意识到它返回的是jQuery对象集合,调用$(":focus").attr("id")总是返回body,后来才明白是只取了集合里最后一个元素的ID; - 有时候
:focus选择器返回空数组,长度为0,不知道原因。
请问在不使用全局焦点追踪的情况下,最优实现方案是什么?
最优实现方案
方案1:用blur事件的relatedTarget属性
blur事件对象自带的relatedTarget属性,直接指向触发blur后获得焦点的元素,这是最直接高效的方法,不需要额外延迟:
$("#field2").on("blur", function(event) { const focusedElement = event.relatedTarget; // 先判断元素存在,再检查ID if (focusedElement && focusedElement.id === "field1") { // 这里写停止操作的逻辑 console.log("切换到field1,停止对应操作"); } });
注意:如果用户点击页面空白处、非可获焦元素(比如div、span),relatedTarget会是null,所以必须先做存在性判断。
方案2:用setTimeout延迟获取焦点元素
blur事件是同步触发的,此时新的焦点元素还没完成focus绑定,延迟0毫秒(让浏览器处理完当前事件队列)后,就能正确拿到当前获焦元素:
$("#field2").on("blur", function() { setTimeout(() => { // 页面同一时间只有一个元素能获焦,取第一个即可 const focusedElement = $(":focus")[0]; if (focusedElement && focusedElement.id === "field1") { // 这里写停止操作的逻辑 console.log("切换到field1,停止对应操作"); } }, 0); });
关于之前:focus选择器问题的解释
- 页面同一时间只会有一个元素处于获焦状态,所以
$(":focus")返回的是长度为0或1的jQuery对象,不会返回多个元素。之前拿到body是因为当没有可编辑元素获焦时,部分浏览器会把焦点给到body; - 触发blur的瞬间,新焦点元素还没完成获焦,此时页面焦点临时回到body,所以直接调用
$(":focus").attr("id")会返回body; :focus返回空数组的情况,是因为blur触发后、新focus触发前的短暂间隙,页面没有元素处于获焦状态。
内容的提问来源于stack exchange,提问作者AckItsMe
相关产品推荐
相关产品推荐

