[英]Listen to all “onClick” events from anchor tags that could possibly contain children
我正在尝试实现一个简单的(-ish)路由器作为练习。 但是,我在检测锚点点击时遇到问题。 理想情况下,我想在URL更改时随时拦截一个事件(不使用哈希),但是现在我只想能够拦截任何锚点事件。
到目前为止,这是我尝试过的:
HTML
<nav id="mainMenu">
<ul id="navlinks">
<li>
<a href="/">
<span>HOME</span>
</a>
</li>
<li>
<a href="/posts">
<span>POSTS</span>
</a>
</li>
</ul>
</nav>
单独的JS文件
function intercept(event)
{
console.log("triggered");
var tag = event.target;
if (
tag.tagName.toUpperCase() === 'A' &&
tag.href &&
event.button == 0 &&
tag.origin == document.location.origin
){
event.preventDefault();
console.log("default prevented")
}
}
使用此代码,我仅检测到span
事件,而不是<a>
事件。 如何使用Vanilla JS检测锚点事件(如果可能)? 我也希望能够检测动态创建的锚点。
编辑1:更改了JS功能。 default prevented: SPAN
打印控制台default prevented: SPAN
:
function intercept(event)
{
console.log("triggered");
var tag = event.target;
//if (
// tag.tagName === 'A'
//){
event.preventDefault();
console.log("default prevented: " + tag.tagName);
//}
}
编辑2:定位标记不会总是有子级,可能的子级可能不是span
。
您需要做的就是从event.target
元素中“遍历文档树”,直到找到一个定位标记。
该解决方案的优点是它利用事件委托,并且可以在页面生命周期中的任何时候运行。 document.documentElement
属性是<html>
标记,它在JavaScript开始执行时就存在。
function findParentByTagName(element, tagName) { var parent = element; while (parent !== null && parent.tagName !== tagName.toUpperCase()) { parent = parent.parentNode; } return parent; } function handleAnchorClick(event) { event = event || window.event; if (findParentByTagName(event.target || event.srcElement, "A")) { event.preventDefault(); console.log("An anchor was clicked!"); } } document.documentElement.addEventListener("click", handleAnchorClick, false);
<p> <a href="#"> <span> <b> <i>Click me!</i> </b> </span> </a> </p> <p> <a href="#">Click me too!</a> </p>
这是因为event.target
将始终指向被单击的最深节点。
event.path
本质上来说, event.path
是您所需要的,但是它尚未得到广泛实施(至今)。
这是如何获取目标的所有父对象的数组,例如event.path会产生:
function getPath(e) {
return e.parentElement? [e].concat(getPath(e.parentElement)) : [e];
}
一旦有了,就可以测试这些元素是否是锚点:
var thereIsAnAnchorInMyPath = getPath(event.target)
.reduce(function(isAnchor, element) {
return isAnchor || /^a$/i.test(element.tagName);
}, false);
您的示例将如下所示:
function intercept(event){
console.log("triggered");
var thereIsAnAnchorInMyPath = (event.path || getPath(event.target))
.reduce(function(isAnchor, element) {
return isAnchor || /^a$/i.test(element.tagName);
}, false);
if (thereIsAnAnchorInMyPath){
event.preventDefault();
console.log("default prevented")
}
}
当然,将事件侦听器附加到锚点会容易得多:
[].slice.call(querySelectorAll('a')).forEach(function(anchor) {
anchor.addEventListener('click', intercept);
});
但是,如果(由于某种原因)将新的锚点插入到文档中,将无法正常工作。 在这种情况下,您需要在每个新锚点插入到文档中后将其附加到一个事件侦听器。
或者,您可以侦听DOM突变事件,然后查询所有锚,过滤已附加事件侦听器的锚,将它们添加到列表中(以便可以在后续事件中过滤它们),最后附加事件侦听器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.