在JavaScript中覆盖链接('a')对象的默认行为

30

我不知道我尝试实现的目标是否可能。我想要覆盖给定HTML页面中所有锚对象(A标记)的默认行为。我知道我可以遍历所有的A元素,并通过body元素的onload方法动态地为每个元素添加一个onclick调用,但我正在寻找一种更绝对的解决方案。我需要的是将所有A元素分配一个onclick操作,该操作调用一个方法,将元素的href属性作为参数传递,如下所示:

<a href="http://domain.tld/page.html">

动态地变成:

<a href="http://domain.tld/page.html" onclick="someMethodName('http://domain.tld/page.html'); return false;">

就像我所说的,最理想的方法是在文档加载时完全覆盖 Anchor 类。如果不可能,那么我会采用遍历所有 A 元素的方法(我已经知道如何做了)。


好的,使用事件委托,它们不需要全部附加事件。例如,请参阅jQuery中的“Live”或阅读有关JavaScript事件委托的文章。 - Nosredna
通常情况下,这应该在HTML传递给客户端之前完成。如果您的页面很复杂,您可能会遇到许多使用事件委托的程序。 - Ben
实际上,对于“click”事件,我预计委托会遇到较少问题。像跟踪鼠标这样的事情会让你崩溃。 - Nosredna
关于jQuery的“Live”请参考以下链接:http://www.zachleat.com/web/2009/05/08/performance-caveat-with-jquery-selectors-and-live-events/ - Nosredna
5个回答

43

如果你不想遍历所有锚点元素,你可以简单地使用事件委托,例如:

document.onclick = function (e) {
  e = e ||  window.event;
  var element = e.target || e.srcElement;

  if (element.tagName == 'A') {
    someFunction(element.href);
    return false; // prevent default action and stop event propagation
  }
};

请在这里查看上面的示例。


6
问题明确提到不要迭代锚元素。 - Ben
2
@Benji XVI:这种方法的优点之一是,如果在绑定此事件后以编程方式添加更多的锚元素(即:使用Ajax加载的内容),它将继续为这些新锚点工作。 - Christian C. Salvadó
1
通常情况下,“最好的选择”取决于具体情况。如果你有很多项,所有这些项都需要运行基本相同的代码,那么委托是非常好的选择。但如果你要进入一个switch语句,并且对每个id都有不同的操作列表,那么委托就不太适合了。 - Nosredna
2
CMS:谢谢,你的方法完美地运行了,简短而精练,正如你在其中一个评论中所说的那样,它实现了对所有“A”元素的应用,而不仅仅是在初始呈现页面上的元素。这个目标是为了允许通过 AJAX 加载的新“A”标签继续工作。干得好! - boliva
3
如果<a>标签内含有DOM元素(如图片,这种情况非常常见),那么此答案将无效。要解决这个问题,需要检查e.path字段并在其祖先中寻找nodeName==='A' - steph643
显示剩余7条评论

8

使用jQuery:

$(function() {
    $("a").click(function() {
        return someMethodName($(this).attr('href'));
    });
});

function someMethodName(href)
{
    console.log(href);
    return false;
}

1

与Benji XVI的答案类似,但使用querySelectorAll,例如在一个带有类名“container”的容器div中,并使用es6。

const $elems = document.querySelectorAll('.container a')
var elems = Array.from($elems)
elems.map(a => {
  a.onclick = (e) => {
    e.preventDefault()
    window.alert('Clicking external links is disabled')
  }
})

0

无法覆盖所有锚点元素的onclick事件。您可以在文档主体中添加一个onclick,并具有用于查看事件是否从锚点元素上升并在这种情况下执行事件的逻辑。但是,如果页面很复杂并且在某些情况下未传播点击,则此解决方案可能会导致问题。

如果可行,我建议坚持使用getElementsByTagName解决方案。


0

CMS的解决方案是最佳的解决方案。请注意,如果您从存储在基础锚点/元素的原型属性集中引用或检查需要运行的函数或检查,可以获得更好的性能。通过使用此属性,您想要调用的函数可以被找到并从一个决策分支中调用,而不是为每种可能性编写新的决策分支。如果您打破或使用具有超过一两个情况的case语句,则应开始考虑今天是否可以进行控制反转和注入式编码。

再次强调,如果有多个事件需要处理,请勿使用case。相反,使用字符串组合构造需要调用的函数的路径。这需要向定义默认值和要组合的字符串的"A"元素添加原型。元素上的数据属性应该能够覆盖默认值。实质上,我们只想通过默认方式传递消息和操作,并在标记中以声明方式更改。指定的操作应该作为API或其他可访问的库函数发布,并且可以通过lib['funName']进行调用。只需给它一个属性,不必担心名称或ID。原型和属性将对去抖动非常有用,因为您将不得不去抖动。

有一些人正在客户端路由器上工作,试图完善它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接