当 event.target 是 HTMLImageElement 时如何获取锚的 href?

Posted

技术标签:

【中文标题】当 event.target 是 HTMLImageElement 时如何获取锚的 href?【英文标题】:How to get href of anchor when the event.target is HTMLImageElement? 【发布时间】:2015-05-27 05:24:28 【问题描述】:

我想在单击锚元素时获取它的href。 我正在使用以下 javascript 代码:

document.addEventListener('click', function (event)

    event = event || window.event;
    var el = event.target || event.srcElement;

    if (el instanceof htmlAnchorElement)
    
        console.log(el.getAttribute('href'));
    
, true);

这非常适合像这样的嵌入式锚:

<div><p><a href='link'></a></p><div>

但是当我使用锚点和图像时它不起作用:

<div><a href='link'><img></a></div>

event.target 正在返回图像而不是锚点。 可以使用以下 if 大小写修改 javascript 代码以解决此问题:

document.addEventListener('click', function (event)

    event = event || window.event;
    var el = event.target || event.srcElement;

    if (el instanceof HTMLImageElement)
    
        // Using parentNode to get the image element parent - the anchor element.
        console.log(el.parentNode.getAttribute('href'));
    
    else if (el instanceof HTMLAnchorElement)
    
        console.log(el.getAttribute('href'));
    
, true);

但这似乎不是很优雅,我想知道是否有更好的方法。

!重要! 注意:请记住,我无权访问 ID 或类,或任何其他传统标识符。我所知道的是会有一个锚点被点击,我需要得到它的href。我什至不知道它会在哪里,是否存在或稍后会创建。

编辑:请不要使用 jQuery 或其他 javascript 库。

【问题讨论】:

您正在寻找.currentTarget 或只是this,它指的是安装处理程序的元素,而不是被点击的元素。 .currentTargetthis 都是 document 元素,因为它使用了事件侦听器。 啊,我错过了你使用全局处理程序。 【参考方案1】:

不要循环 DOM 中的所有锚点,而是从 event.target 元素中查找。 使用 JavaScript 的.closest() MDN Docs(PS:polyfill for IE)

addEventListener('click', function (event) 
  event.preventDefault();                     // Don't navigate!
  const anchor = event.target.closest("a");   // Find closest Anchor (or self)
  if (!anchor) return;                        // Not found. Exit here.
  console.log( anchor.getAttribute('href'));  // Log to test
);
<a href="http://***.com/a/29223576/383904">
  <span>
      <img src="//placehold.it/200x60?text=Click+me">  
  </span>
</a>

<a href="http://***.com/a/29223576/383904">
  Or click me
</a>

它基本上像 jQuery 的 .closest() 那样工作

最近的或自己的(找到最近的父母...否则 - 瞄准我!)

在上面的例子中得到了更好的描述。

【讨论】:

这是一个非常棒的解决方案。它比我的解决方案更具前瞻性和可维护性。但是,它具有糟糕的浏览器支持。 :( @AurelijeAure 我喜欢推动 www 向前发展,所以我预计在不久的将来会有大量的使用,因为这种方法是一种生活标准,尚未被所有供应商采用。 现在我想起来了,如果页面上存在锚点,该解决方案将在每次单击时获得一个 href,因为它会继续解析 DOM,直到找到一个。跨度> @AurelijeAure 是的,因为它使用 document - 而是使用 Array.from 传递 document.querySelectorAll('a') 并将侦听器添加到每个 Anchor 元素。为了确保它真的有一个href,你可以使用属性选择器document.querySelectorAll('a[href]') 确实是一个很棒的解决方案。 event.target.href 给了我 undefined【参考方案2】:

与其添加一个全局的click 处理程序,为什么不只针对锚标记?

var anchors = document.getElementsByTagName("a");
for (var i = 0, length = anchors.length; i < length; i++) 
  var anchor = anchors[i];
  anchor.addEventListener('click', function() 
    // `this` refers to the anchor tag that's been clicked
    console.log(this.getAttribute('href'));
  , true);
;

如果您想坚持使用文档范围的 click 处理程序,那么您可以向上爬,以确定点击的内容是否包含在这样的链接中:

document.addEventListener('click', function(event) 
    event = event || window.event;
    var target = event.target || event.srcElement;

    while (target) 
      if (target instanceof HTMLAnchorElement) 
        console.log(target.getAttribute('href'));
        break;
      

      target = target.parentNode;
    
, true);

这样至少您可以避免编写必须考虑所有可能类型的锚子和嵌套结构的脆弱代码。

【讨论】:

只是写了相同的答案,这是要走的路。 我已经考虑过这一点,但我想知道页面上的锚点数量是否会使循环成为不必要的性能问题。更不用说所有生成的 javascript 代码了。另外,正如我在笔记中所解释的,我不知道带有锚的元素是否存在,而您的解决方案假设它存在。有一些解决方法,但它们并不漂亮。 这真是一段优秀的代码!不是我所希望的乌托邦式解决方案,但它会奏效。谢谢。

以上是关于当 event.target 是 HTMLImageElement 时如何获取锚的 href?的主要内容,如果未能解决你的问题,请参考以下文章

$(this)和event.target之间的区别?

ReactJS event.target.value 返回未定义

event.target指向谁?

event.target与event.currentTarget的区别

上传文件事件并校验:event.target.files && event.target.files[0]

event.target与event.srcElement