Javascript 倾听所有人的声音;onClick";来自可能包含子项的锚定标记的事件
我试图实现一个简单的(-ish)路由器作为练习。但是,我在检测锚点点击时遇到问题。理想情况下,我希望在URL更改时拦截事件(不使用哈希),但现在我只希望能够拦截任何锚单击事件 以下是我到目前为止所做的尝试: HTMLJavascript 倾听所有人的声音;onClick";来自可能包含子项的锚定标记的事件,javascript,html,onclick,anchor,dom-events,Javascript,Html,Onclick,Anchor,Dom Events,我试图实现一个简单的(-ish)路由器作为练习。但是,我在检测锚点点击时遇到问题。理想情况下,我希望在URL更改时拦截事件(不使用哈希),但现在我只希望能够拦截任何锚单击事件 以下是我到目前为止所做的尝试: HTML <nav id="mainMenu"> <ul id="navlinks"> <li> <a href="/"> <span>HOME<
<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>
使用此代码,我只检测span
事件,而不是
事件。使用vanilla JS(如果可能的话)我可以做些什么来检测锚点点击事件?我希望能够检测动态创建的锚以及
编辑1:更改了JS函数。控制台打印禁止的默认值: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.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变异事件,然后查询所有锚点,筛选已附加事件侦听器的锚点,将它们添加到列表中(以便在后续事件中进行筛选),最后附加事件侦听器。您需要做的就是“遍历文档树”从event.target
元素,直到找到锚定标记
此解决方案的优点是它利用了事件委派,并且可以在页面生命周期的任何时候运行。document.documentElement
属性是
标记,它在JavaScript开始执行时就存在
函数findParentByTagName(元素,标记名){
var父元素=元素;
while(parent!==null&&parent.tagName!==tagName.toUpperCase()){
parent=parent.parentNode;
}
返回父母;
}
函数句柄单击(事件){
event=event | | window.event;
if(findParentByTagName(event.target | | event.srcElement,“A”)){
event.preventDefault();
log(“锚被点击了!”);
}
}
document.documentElement.addEventListener(“单击”,手动单击,错误)代码>
注释掉一些条件谓词,直到它按预期工作,然后重新修改条件。要检测导航尝试,您可以在正文上卸载之前侦听。@dandavis我的所有条件现在都消失了。它仍然只检测跨距点击。@dtanders这会让我阻止页面卸载吗?您如何绑定处理程序?这是一个很好的解决方案,但我将使用Greg Burghardt的答案,因为它更容易理解。我稍微修改了代码,以便访问检测到的锚标记(将findParentByTargetName
的结果分配给局部变量)。我无法摆脱这样一种感觉,即这更像是一种解决办法。也许现在不可能。这是执行事件委派的基本方法。所有主要的JavaScript库或框架都从事件开始。target
并在文档树上漫游,直到满足某个条件。我创建了一个事件委派库很少见的是,你可以插入到现有的代码中。它比这个解决方案更加健壮,但我不确定它是否适用于你的单页应用程序。
[].slice.call(querySelectorAll('a')).forEach(function(anchor) {
anchor.addEventListener('click', intercept);
});