使用jQuery/javascript测试链接是否在外部?

Mat*_*rym 62 javascript jquery location href

如何测试链接是外部链接还是内部链接?请注意:

  1. 我无法对本地域进行硬编码.
  2. 我无法测试"http".我可以通过http绝对链接轻松链接到我自己的网站.
  3. 我想使用jQuery/javascript,而不是css.

我怀疑答案位于location.href的某个地方,但解决方案避开了我.

谢谢!

Dav*_*ved 56

我知道这篇文章很老但它仍然显示在结果的顶部,所以我想提供另一种方法.我看到所有正则表达式检查一个锚元素,但为什么不使用window.location.host和检查元素的host属性?

function link_is_external(link_element) {
    return (link_element.host !== window.location.host);
}
Run Code Online (Sandbox Code Playgroud)

使用jQuery:

$('a').each(function() {
    if (link_is_external(this)) {
        // External
    }
});
Run Code Online (Sandbox Code Playgroud)

并使用普通的javascript:

var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
    if (link_is_external(links[i])) {
        // External
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是唯一对我有意义的答案 - 其他人都是过度设计的.有没有反对这种方法的论据? (7认同)

jAn*_*ndy 47

var comp = new RegExp(location.host);

$('a').each(function(){
   if(comp.test($(this).attr('href'))){
       // a link that contains the current host           
       $(this).addClass('local');
   }
   else{
       // a link that does not contain the current host
       $(this).addClass('external');
   }
});
Run Code Online (Sandbox Code Playgroud)

注意:这只是一个快速而肮脏的例子.它会将所有href ="#anchor"链接匹配为外部链接.可以通过执行一些额外的RegExp检查来改进它.


更新2016-11-17

这个问题仍然有很多流量,很多人告诉我,这个接受的解决方案会在几次失败.正如我所说,这是一个非常快速和肮脏的答案,以显示如何解决这个问题的主要方式.更复杂的解决方案是使用<a>(锚)元素上可访问的属性.就像@Daved在这个答案中已经指出的那样,关键是要比较hostname当前的情况window.location.hostname.我更愿意比较hostname属性,因为它们从不包括属性中port包含的host属性,如果它与80不同.

所以我们走了:

$( 'a' ).each(function() {
  if( location.hostname === this.hostname || !this.hostname.length ) {
      $(this).addClass('local');
  } else {
      $(this).addClass('external');
  }
});
Run Code Online (Sandbox Code Playgroud)

最先进的:

Array.from( document.querySelectorAll( 'a' ) ).forEach( a => {
    a.classList.add( location.hostname === a.hostname || !a.hostname.length ? 'local' : 'external' );
});
Run Code Online (Sandbox Code Playgroud)

  • http://jsfiddle.net/zuSeh/验证此方法不适用于相对网址. (10认同)
  • 我很确定这不适用于相对网址.`attr`应该返回属性,而不是属性(属性可能被解析,而不是属性). (7认同)
  • 如果使用href属性而不是href属性,它也适用于相对属性. (4认同)
  • 我看到人们仍在查看这个问题和解决方案,所以我想链接到我提出的解决方案,下面应该处理没有RegEx或相关问题的所有检查:http://stackoverflow.com/a/18660968/2754848 (2认同)

Sea*_*sey 37

并且没有jQuery的方式

var nodes = document.getElementsByTagName("a"), i = nodes.length;
var regExp = new RegExp("//" + location.host + "($|/)");
while(i--){
    var href = nodes[i].href;
    var isLocal = (href.substring(0,4) === "http") ? regExp.test(href) : true;
    alert(href + " is " + (isLocal ? "local" : "not local"));
}
Run Code Online (Sandbox Code Playgroud)

所有不以http(http://,https://)开头的href都会自动视为本地

  • 如果您使用协议不可知的URL,这将无效,即:`href ="// somedomain.com/some-path"` (7认同)
  • 这与解决方案很接近,但您还应该检查href属性是否以`location.protocol +'//'+ location.host`开头.检查这个小提琴:http://jsfiddle.net/framp/Ag3BT/1/ (2认同)
  • 你为什么用while循环这样做?在我看来,通过$(document).on('click','a',function({})使用事件委托更有意义;并测试点击的特定链接(点击时)那样,你不必在页面上的所有链接上不必要地循环,它将允许在初始DOM准备好之后通过ajax添加到页面的任何元素...有时候实际上有一点使用jQuery(超出是一个"粉丝"). (2认同)

Jam*_*mes 7

var external = RegExp('^((f|ht)tps?:)?//(?!' + location.host + ')');
Run Code Online (Sandbox Code Playgroud)

用法:

external.test('some url'); // => true or false
Run Code Online (Sandbox Code Playgroud)


Bla*_*ger 7

这是一个只有外部链接的jQuery选择器:

$('a[href^="(http:|https:)?//"])') 
Run Code Online (Sandbox Code Playgroud)

仅用于内部链接(不包括同一页面中的哈希链接)的jQuery选择器需要更复杂一些:

$('a:not([href^="(http:|https:)?//"],[href^="#"],[href^="mailto:"])')
Run Code Online (Sandbox Code Playgroud)

可以在:not()条件内放置其他过滤器,并根据需要使用其他逗号分隔.

http://jsfiddle.net/mblase75/Pavg2/


或者,我们可以使用vanilla JavaScript href属性过滤内部链接,该属性始终是绝对URL:

$('a').filter( function(i,el) {
    return el.href.indexOf(location.protocol+'//'+location.hostname)===0;
})
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/mblase75/7z6EV/


小智 6

你忘了一个,如果你使用相对路径会怎么样.

例如:/ test

        hostname = new RegExp(location.host);
            // Act on each link
            $('a').each(function(){

            // Store current link's url
            var url = $(this).attr("href");

            // Test if current host (domain) is in it
            if(hostname.test(url)){
               // If it's local...
               $(this).addClass('local');
            }
            else if(url.slice(0, 1) == "/"){
                $(this).addClass('local'); 
            }
            else if(url.slice(0, 1) == "#"){
                // It's an anchor link
                $(this).addClass('anchor'); 
            }
            else {
               // a link that does not contain the current host
               $(this).addClass('external');                        
            }
        });
Run Code Online (Sandbox Code Playgroud)

还存在文件下载.zip(本地外部)的问题,可以使用"本地下载"或"外部下载"类.但是还没有找到解决方案.


小智 6

const isExternalLink = (url) => {
    const tmp = document.createElement('a');
    tmp.href = url;
    return tmp.host !== window.location.host;
};

// output: true
console.log(isExternalLink('https://foobar.com'));
console.log(isExternalLink('//foobar.com'));

// output: false
console.log(isExternalLink('https://www.stackoverflow.com'));
console.log(isExternalLink('//www.stackoverflow.com'));
console.log(isExternalLink('/foobar'));
console.log(isExternalLink('#foobar'));
Run Code Online (Sandbox Code Playgroud)

使用这种方法的好处是:

  • 它会自动解析hostname相对路径和片段;
  • 它适用于protocol-relativeURL

为了证明这一点,让我们看一下以下示例:

const lnk = document.createElement('a');
lnk.href = '/foobar';

console.log(lnk.host); // output: 'www.stackoverflow.com'
Run Code Online (Sandbox Code Playgroud)
const lnk = document.createElement('a');
lnk.href = '#foobar';

console.log(lnk.host); // output: 'www.stackoverflow.com'
Run Code Online (Sandbox Code Playgroud)
const lnk = document.createElement('a');
lnk.href = '//www.stackoverflow.com';

console.log(lnk.host); // output: 'www.stackoverflow.com'
Run Code Online (Sandbox Code Playgroud)