【问题标题】:Best way to find nearest href attribute?找到最近的 href 属性的最佳方法?
【发布时间】:2015-05-20 18:45:11
【问题描述】:

为什么我认为它不是重复的。

嗯,我认为这与我的要求略有不同。我不 想要为所有 A 标签添加一个监听器,而不是减去一个 href 属性,如果有的话,在点击事件的目标上。

我正在尝试“Ajaxify”我的整个网站,以便当用户单击页面中包含的任何链接时,脚本会将“url”或 HREF 属性(被单击的元素)发送到 Ajax 函数,作为回报,呈现请求的内容(如单击的链接所示)。

如果元素是链接,我需要找到被点击元素的HREF 属性。 这里的问题,很多元素可以包含在一个 A 标记中(因为我构造它们的方式),而 e.target.href 不一定总是返回 HREF 属性。

这是我目前所拥有的:

function ajaxifyLinks(e) {
    var target = e.target;
    e.preventDefault();
    while(!target.href) {
        target = target.parentNode;
    }
    if(target.href) {
        ajaxLoad(target.href);
    }
}
document.body.addEventListener('click', ajaxifyLinks);

以下是我拥有的不同“可点击”链接的示例:

<!-- Link -->
<a href="/cats">
   cats
</a>

<!-- Link -->
<a href="/hello">
   <span>
      <span> hi </span>
   </span>
</a>

<!-- Link -->
<a href="/bye">
   <span>
      bye
   </span>
</a>

如您所见,这就是e.target.href 不会总是返回 HREF 属性的原因,因为您实际上是在单击“链接”的 span 元素,但是,浏览器确实会将您带到链接。为什么会这样?有什么方法可以让我从这种行为中受益吗? (例如,提取浏览器将您带到的位置,即使您没有点击 A 标签)。

我不喜欢我的解决方案,因为 while 循环只是不断查找 DOM 树,有时是不必要的(当 e.target 不是链接或包含在链接中时)。

谢谢。

【问题讨论】:

  • document.querySelectorAll("a[href]") ?
  • 对不起,但实际上并不清楚您要实现什么。请描述您尝试解决的实际问题(您尝试添加到站点的行为),而不是您尝试的解决方案。请避免使用XY problem 来描述解决方案的问题而不描述实际的最终目标。
  • 您可以在大多数 HTML 元素上监听 click 事件。
  • 好的,我编辑了这个问题。现在清楚了吗? (对于慷慨的 cmets,请参阅上面编辑过的问题,谢谢)。
  • 我意识到这一点,但我并不想在这个项目中使用 jQuery。无论如何,我在哪里可以找到 jQuery 实现它的方式?

标签: javascript ajax find href


【解决方案1】:

如果单击的元素没有 href,它会在其父元素中搜索具有 href 的元素。香草 JS 解决方案。

function findUpTag(el, attr) {
    while (el.parentNode) {
        el = el.parentNode;
        if (el[attr]) {
            return el;
        }
    }
    return null;
}

document.body.onclick = function (event) {
    event.preventDefault();

    var href = event.target.href;
    
    if (!href) {
        var closest = findUpTag(event.target, 'href');
        if (closest) {
            href = closest.href;
        }
    }

    document.getElementById('output').innerHTML = 'element clicked: ' + event.target.nodeName + '<br>closest href: ' + href;
};
a,
output {
    display: block;
}
<!-- Link -->
<a href="/cats">
   cats
</a>

<!-- Link -->
<a href="/hello">
   <span>
      <span> hi </span>
   </span>
</a>

<!-- Link -->
<a href="/bye">
   <span>
      bye
   </span>
</a>

<output id="output"></output>

【讨论】:

  • 太好了,效果很好,感谢您的努力!我认为这比我使用 while 循环要好。
  • 它仍然使用while循环,但不同之处在于它一旦找到带有href的元素就会停止。
【解决方案2】:

使用.parent(),参考:http://api.jquery.com/parent/

例如,你可以这样做

var hrefElem = $(target).parent('*[href]');
var link = hrefElem.attr('href');

【讨论】:

    【解决方案3】:

    新答案:

    <!-- Link -->
    <a href="/cats">
       cats
    </a>
    
    <!-- Link -->
    <a href="/hello">
       <span style="pointer-events: none;">
          <span style="pointer-events: none;"> hi </span>
       </span>
    </a>
    
    <!-- Link -->
    <a href="/bye">
       <span style="pointer-events: none;">
          bye
       </span>
    </a>

    【讨论】:

    • OP 提到他不想在 cmets 中使用 jQuery。
    • 他一定是在我写答案的时候添加了更多细节...当我开始回答时没有 HTML 示例...但是,有一个简单的跨浏览器 CSS 解决方案:添加指针-events:none 到 SPAN,它应该可以工作... ;) 事件将直接从 SPAN 传递到父 A 标签!
    • 我重写了我的答案... ;)
    • 这实际上是一个非常酷的解决方案,我不知道你可以用 CSS 做到这一点。我试过这个并且它有效。我认为唯一的缺点是,如果链接中有 DIV 元素(我认为 HTML5 现在允许这样做),因为我将该属性分配给 div 元素,并且由于某种原因,链接变得不可点击。然而,这对我来说不是这样,这是有意的。我对选择什么作为答案存在分歧,因为这和 Moogs 的解决方案运作良好。
    • 它实际上因您的需要而异。我总是建议我的团队努力为我们构建的产品创建最简单、最简洁的 HTML 结构。当我们需要操作 DOM 对象和事件时,它简化了流程。没有“一个解决方案适合所有人”这样的事情,您能做的最好的事情就是注释这些可能性并逐案实施(始终牢记,随着项目的进展,简单会得到回报)。
    【解决方案4】:

    只需将点击处理程序附加到页面上的每个链接:

    function ajaxify(e)
    {
        e.preventDefault();
        ajaxLoad(this.href);
    }
    
    [].forEach.call(document.getElementsByTagName('a'), function(el) {
        el.addEventListener('click', ajaxify.bind(el));
    });
    

    【讨论】:

      【解决方案5】:

      查看What is event bubbling and capturing? 以了解事件如何通过 DOM 传播。

      捕获锚链接并通过 Ajax 加载它们的技术称为Hijax。因为您要替换页面上的内容,所以您不能简单地设置一个事件来处理所有链接,并且您可能不想继续重新绑定每个页面加载,所以您使用的方法很好,并且被称为event delegation

      上一篇文章准确地描述了您的问题(就在最后),并且还描述了与您的类似的解决方案,这确实是在这种情况下解决问题的最佳方法。但是,您可以考虑使用微型库来简化一些事件委托;一个例子是gator.js

      【讨论】:

        猜你喜欢
        • 2014-04-28
        • 1970-01-01
        • 2020-02-14
        • 2010-11-01
        • 2021-10-28
        • 2016-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多