找到最近的 href 属性的最佳方法?

Best way to find nearest href attribute?

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

Hmm, I think that's slightly different to what I'm asking. I don't want to add a listener to all A tags, rather, substract an href attribute, if any, on a click event's target.

我正在尝试 "Ajaxify" 我的整个站点,以便当用户单击页面中包含的任何 link 时,脚本会发送 "url" 或 HREF 属性(被点击的元素)添加到 Ajax 函数,该函数在 return 中呈现请求的内容(如 link 所点击的所示)。

如果元素是 link,我需要找到被单击元素的 HREF 属性。 这里的问题 是许多元素可以包含在 A 标签中(因为我构建它们的方式),并且 e.target.href 不一定总是 return 一个 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);

下面是我拥有的不同 "clickable" link 的示例:

<!-- 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 不会总是 return HREF 属性,因为您实际上是在单击 "linked" span 元素,但是,浏览器会带你去link。为什么会这样?有什么方法可以让我从这种行为中受益吗? (例如,提取浏览器将您带到的位置,即使您没有点击 A 标签)。

我不喜欢我的解决方案,因为 while 循环一直在查找 DOM 树,有时是不必要的(当 e.target 不是 link 或包含在link).

谢谢。

新答案:

<!-- 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>

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

例如,您可以

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

如果单击的元素没有 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>

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

function ajaxify(e)
{
    e.preventDefault();
    ajaxLoad(this.href);
}

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

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

捕获锚链接并通过Ajax加载它们的技术被称为Hijax. Because you're replacing content on the page, you can't simply set up a single event to handle all links, and you probably don't want to keep re-binding every page load, so the approach you are using is good, and is known as event delegation

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