JavaScript:全局元素焦点监听器

15

我正在尝试设置一个监听器,以便监听所有的焦点事件。特别是,我正在尝试监听任何输入框或文本框获得焦点的时刻。根据一些研究,广泛接受的方法是这样的:

document.body.onfocus = function(event) {
   //Check the event.target for input/textbox
   //Do something
};

但是 document.body.onfocus 似乎从来没有触发过。我认为可能是因为文档实际上从来没有获得焦点,所以我尝试了:

document.body.focus();

最初“设置”焦点,但这也不起作用。

有没有想法可以在所有输入框/文本框上侦听焦点事件,而不必直接在元素本身上设置事件?请使用原生JavaScript,不要使用框架。

根据接受的答案,这里是一些可工作的代码:

var focusHandler = function(event) {
    var type = event.target.nodeName.toLowerCase();
    if(type == 'input' || type == 'textarea') {
        //Do something
    }
};
document.body.addEventListener('focus', focusHandler, true); //Non-IE   
document.body.onfocusin = focusHandler; //IE

你在哪里运行这段代码?在<head>标签中吗?还是在<body>标签中?我认为当在<head>标签中运行代码时,document.body将不可用...虽然不确定。 - Ian
一个单独的js文件。完全不在html中。 - ryandlf
但是在你的HTML文件中,JS文件被包含在哪里? - Ian
正文。我经常使用document.body来处理正文上的点击事件,所以这不是问题所在。 - ryandlf
1
https://dev59.com/tG035IYBdhLWcg3wMM4G - 它不会冒泡 - Ian
2个回答

13

由于一些事件(如焦点、模糊、更改)不会冒泡,因此建议您尝试使用 事件捕获(Event Capturing)。首先,onfocus 对此无效,因此您必须使用 addEventListener,在第三个参数中指定所使用的委托模式。请查看MDN 中关于使用 addEventListener 的说明。

另外,请参阅这篇文章,了解有关将焦点事件委托上升的更多信息。


运行得非常好。文章也很棒。我一直想知道事件监听器末尾的那个 false 是干什么用的!使用一些可运行的代码更新 OP。 - ryandlf
7
这个答案应该包括这些链接背后的相关信息,例如使用parentElement.addEventListener("focus", listener, true)中第三个参数为true可以启用事件捕获。 - Sebastian Simon

7
focus事件不会从元素向其祖先元素冒泡,因此您无法使用事件委托(将其钩在body上,并查看body的所有后代)来检测它。
有一个更新的事件focusin(由Microsoft创新,现在也可用于其他浏览器),它确实会冒泡,因此根据您想要支持哪些浏览器,这可能适用于您。

1
请查看这篇有趣的文章,了解更多信息和巧妙的技巧:http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html - Marcus Ilgner
1
当然,如果您愿意使用库,jQuery可以使focusblur以跨浏览器的方式冒泡,而无需担心它。 - T.J. Crowder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接