在 DOM 中的所有元素上附加 click 事件的事件处理程序

Posted

技术标签:

【中文标题】在 DOM 中的所有元素上附加 click 事件的事件处理程序【英文标题】:Attach event handlers for click event on all elements in the DOM 【发布时间】:2014-05-07 04:43:14 【问题描述】:

我希望能够确定我的页面的哪一部分被点击了。不能保证元素从一开始就在页面上,这意味着我需要使用 jQuery 委托之类的东西。

一种方法是遍历 DOM 中的所有元素,然后将事件处理程序附加到每个元素 - 但这会很慢而且很复杂 - 每次动态添加新的 html 时,我都必须重新- 附加所有处理程序,或找出添加的 html 子集。

另一种方法是使用事件冒泡 - 因此将事件处理程序添加到文档或正文并依赖于冒泡的事件。

类似这样的:

$('body').delegate('div', 'click', function(e)
    dummyId++;
    console.log(e);
    console.log(e.currentTarget);
    console.log("=====");

);

但是,在使用此代码后,当我单击页面上的按钮时,我会看到按钮周围的 div,而不是实际的按钮。换句话说,上面的内容太具体了。此外,我觉得原始选择器应该是文档,而不是正文标签。

明确地说,我想知道何时点击了我的页面上的任何元素 - 我该怎么做?

所以我用.on 尝试了这段代码:

$(document).on('click', function(e)
    console.log("EVENT DUMMY ID");

    console.log(e.target);
    console.log("=====");

);

但是,当我单击应用程序中的按钮时,什么都不会触发 - 当我单击其他元素时,控制台日志会运行。

我知道如果没有更多上下文,这可能很难回答 - 你还需要什么?

【问题讨论】:

不要使用基于选择器的委托。只需将处理程序绑定到document,然后检查e.target。这将是点击次数最多的元素。 $(document).on("click", function(e) console.log(e.target.nodeName); ) on 无法工作 - 我动态附加 html 元素 在你说它不能工作之前,先试试吧。没有理由它不适用于动态创建的元素,假设我已经正确理解您想要最深点击的元素。 我已经尝试过了 - api.jquery.com/on - 也支持我 - “事件处理程序仅绑定到当前选定的元素;它们必须在您的代码调用时存在于页面上。上()。” cookie monster 的代码将起作用,正是因为他绑定到文档 - 从一开始就存在的元素 - 并且只有在回调中询问调用事件的实际元素时,无论是从一开始就在那里或后来添加。 【参考方案1】:

currentTarget 返回事件冒泡的节点(如果有的话)。而是询问target,所以:

原版:

document.addEventListener('click', function(evt) 
    alert(evt.target.tagName);
, false);

jQuery:

$(document).on('click', function(evt) 
    alert(evt.target.tagName);
);

http://jsfiddle.net/qsbdr/

【讨论】:

这个小提琴显示 addEventListener 处理动态添加的元素。 jsfiddle.net/qsbdr/2【参考方案2】:

只需这样做:

var listener = function handleClick(event)
    element = event.target
    console.log(element) 
    

var body = document.body
body.addEventListener('click', listener, true);

这将打印在 DOM 上单击的元素。

【讨论】:

【参考方案3】:

我遇到了相同类型的问题,以找出在导航栏上单击了哪个元素。我在动画幻灯片中工作。所以,为了解决这个问题,我尝试处理<ul>的所有事件

注意事项:这只是一块块。不是整个网页。

这是我的 reactjs 代码。概念是一样的。

jsx

        <ul className="right" onClick=setRainbow>
            <li><Link to="/">Home</Link></li>
            <li><NavLink to="/about">About</NavLink></li>
            <li><NavLink to="/contact">Contact</NavLink></li>
        </ul>

功能

    const setRainbow = (e) => 
            console.log(e.target)
            console.log(e.target.href)
            console.log(e.target.text)
        if (e.target.text === 'About') 
            // to do
         else 
            // to do
        
    

【讨论】:

【参考方案4】:

试试这个:

$(document).on('click', function(e) 
   // now use e.target here
);

你也可以使用e.stopPropagation()杀死点击事件的冒泡

【讨论】:

另外,在 jQuery 中你不需要 e.target ? e.target : e.srcElement。它为你做到了。并且 .live() 已从 jQuery 中删除。 如果他使用旧的 jquery live() 有没有... on() 从 1.7 版开始添加 没错,但.live() 的工作方式,它依赖于传递的选择器。执行$(document).live( 将不起作用,因为它没有提供用于委托的选择器。将.live() 更改为.bind() 以适应旧版本的jQuery,它会工作。 是的,没关系.. 看起来他正在使用更新版本的 jQuery 请注意,对于页面上其他按钮的点击事件,这些按钮的点击功能中不应包含e.stopPropagation();...否则不会触发文档上的此点击事件您单击页面上的此类按钮...如果有人遇到此类问题,我只是想提一下...【参考方案5】:

我认为没有必要使用 jQuery 来完成类似的事情,尽管我的建议确实依赖于 MutationEvents,我知道它会被替换。

您可以在将任何新节点插入 DOM 时收到通知。在触发的回调中,您可以简单地将 onclick 处理程序附加到新节点。我只处理了添加新节点的情况。

<!DOCTYPE html>
<html>
<head>
<script>
window.addEventListener('load', onDocLoaded, false);

function onDocLoaded()

    window.addEventListener('DOMNodeInserted', onNodeInserted, false);
    document.body.appendChild( newEl('div') );


function onNodeInserted(evt)

    evt.srcElement.addEventListener('click', onNodeClicked, false);


function onNodeClicked()

    document.body.appendChild( newEl('div') );

</script>
<style>
div

    border: solid 1px red;
    padding: 8px;
    margin: 4px;
    display: inline-block;

</style>
</head>
<body>
</body>
</html>

【讨论】:

浏览器支持怎么样? IE9,Opera 12.15,Chrome 33.0.1750.154 m,android 2.3 上的默认浏览器。所有测试和功能。

以上是关于在 DOM 中的所有元素上附加 click 事件的事件处理程序的主要内容,如果未能解决你的问题,请参考以下文章

移动端touch事件影响界面click/超链接事件无法点击

将 onclick/ng-click 事件附加到网格数据绑定事件中的元素

dojo:哪些事件附加到元素?

取消绑定 ng-click 以获取角度中的动态 dom 元素

从click事件理解DOM事件流

Meteor - 新 DOM 元素上的事件 [重复]