我正在尝试将一个简单的(-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
:
function intercept(event)
{
console.log("triggered");
var tag = event.target;
//if (
// tag.tagName === 'A'
//){
event.preventDefault();
console.log("default prevented: " + tag.tagName);
//}
}
编辑2 :锚标记并不总是有孩子,可能的孩子可能不是span
。
答案 0 :(得分:4)
您需要做的就是#34;走上文档树&#34;从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);
&#13;
<p>
<a href="#">
<span>
<b>
<i>Click me!</i>
</b>
</span>
</a>
</p>
<p>
<a href="#">Click me too!</a>
</p>
&#13;
答案 1 :(得分:1)
因为event.target
将始终指向被点击的最深节点。
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突变事件,然后查询所有锚点,过滤掉已经附加事件侦听器的那些,将它们添加到列表中(这样您可以在后续事件中对它们进行过滤)并最终附加事件听众。