在 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 事件的事件处理程序的主要内容,如果未能解决你的问题,请参考以下文章
将 onclick/ng-click 事件附加到网格数据绑定事件中的元素