如何仅将 target="_blank" 自动添加到外部链接?

Posted

技术标签:

【中文标题】如何仅将 target="_blank" 自动添加到外部链接?【英文标题】:How to automatically add target="_blank" to external links only? 【发布时间】:2012-08-16 00:51:16 【问题描述】:

我正在构建一个自定义的、特定于行业的 cms(使用 django)。在后端,网站管理员可以指定一个内部链接,例如“/page1”或用于整个网站的各种导航元素的外部链接(渲染时都使用<a>)。问题是我希望在当前选项卡中打开内部链接,但外部链接应该使用target="_blank" 打开新选项卡或窗口。

如何处理 html 以完成此操作?

我更喜欢服务器端解决方案,但我不知道在 django 中预处理渲染模板的任何干净方法。因此,我认为最直接的方法可能是 javascript/jquery 解决方案:在每个页面加载时运行的脚本,它将 target="_blank" 属性添加到所有外部链接而不是内部链接。但我也不知道该怎么做。

【问题讨论】:

我刚刚对其进行了编辑,以使以前(并且相当明显)隐含的问题明确。 id 使用中间件在服务器端执行此操作,该中间件解析响应并替换所需位置的代码。您可以使用 beautifulsoup 进行解析。 【参考方案1】:

我建议你做那个服务器端。 根据链接的位置修改页面的模板。

【讨论】:

虽然我很欣赏你的观点,但我想我会等着看是否有人真的可以建议如何使用 django 在服务器端完成。【参考方案2】:

试试类似的东西

for (var links = document.links, i = 0, a; a = links[i]; i++) 
        if (a.host !== location.host) 
                a.target = '_blank';
        

不要忘记在文档树中存在所有链接时运行脚本 - 在window.onload 事件中。

【讨论】:

我认为使用 jQuery 的 .ready() 代替 window.onload 会更合适,因为 .ready() 会在 DOM 完全加载后立即触发,而 window.onload 直到所有资源都不会触发已加载(图像等),这意味着用户有可能在添加目标之前点击。 @strille 这个问题没有被标记为 jQuery,所以我不想使用它,而且我不想让 OP 与DOMContentLoaded + 后备解决方案混淆,因为它不是跨浏览器的。但你是对的。 很抱歉忘记了最初的 jquery 标签。如果需要,请随时使用 jquery 修改答案。无论哪种方式,我都投了赞成票。【参考方案3】:

我一直在使用以下内容。不记得我最初在哪里找到的:

$.expr[':'].external = function(obj)
    return !obj.href.match(/^mailto\:/)
           && (obj.hostname != location.hostname)
           && !obj.href.match(/^javascript\:/)
           && !obj.href.match(/^$/)
;

这增加了一个:external jQuery 选择器,所以你可以这样做:

$('a:external').attr('target', '_blank');

使用自定义选择器的好处在于,如果您需要修改构成“外部”链接的内容,您可以在一处更改它,而不必担心其余代码。例如,在我的组织中,我们有某些不是“外部”的子域,但我们仍想在新窗口中打开。

【讨论】:

这很酷。我以前从未以这种方式扩展 jquery,但我喜欢简单的用法,以及您提到的优点。 这种确定主机名是在现场还是在现场外的方法非常好。比我的更彻底。 这太棒了。谢谢。 多年来我一直在生产中毫无问题地使用它,显然至少有 17 人认为它有效。它怎么不适合你?你有什么错误吗?【参考方案4】:

你可以这样做:

$(document.body).on('mouseover', 'a[target!=_blank]:not(.local)', function (evt) 
    var a = $(this);
    var href = a.attr('href');
    var domain = href.match(/^https?:\/\/([^:\/]+)/);
    if (domain && domain[1] && domain[1] !== "yourdomain.com") 
        a.attr('target', '_blank');
     else 
        a.addClass('local');
    
);

这将在您单击每个链接时对其进行处理,并且不应多次处理每个链接。如果它需要是外部的,target 将被设置为_blank,它应该在一个新窗口中打开。 Here's a working jsfiddle.

更新:我确定链接是否留在现场的方法非常粗略。 this answer中的方法比较彻底。我可能会用该测试替换我的简单正则表达式匹配。

【讨论】:

有趣的实时解决方案。 还没有完全工作。现在必须帮助面试,但稍后会回来编辑。 我想我更喜欢克里斯的回答,但我已经对你的回答投了赞成票。所以请随意清理它;只是想我会提醒你我可能会朝着不同的方向前进,所以不要着急。 他的回答很好。我能想到我的优势的唯一方法是您可以使用 javascript 动态添加链接,它们将自动工作,而无需您再次运行此代码。这就是.on 函数的美妙之处:)【参考方案5】:

你也可以这样做:

$("a[href^='http://']").attr("target","_blank");

$('a').each(function() 
   var a = new RegExp('/' + window.location.host + '/');
   if(!a.test(this.href)) 
       $(this).click(function(event) 
           event.preventDefault();
           event.stopPropagation();
           window.open(this.href, '_blank');
       );
   
);

【讨论】:

【参考方案6】:

代码稍有改动,不会报错,额外= in !==

$.expr[':'].external = function(obj)
    return !obj.href.match(/^mailto\:/) && (obj.hostname !== location.hostname) && !obj.href.match(/^javascript\:/) && !obj.href.match(/^$/);
;
$('a:external').attr('target', '_blank');

【讨论】:

【参考方案7】:

另一种 JavaScript 解决方案:

(() => 
  (document.querySelectorAll('a')).forEach(link => 
    link.hostname !== location.hostname && link.setAttribute('target', '_blank');
  )
)();

【讨论】:

【参考方案8】:

@Chris Pratt 的公认答案不适用于例如电话:链接和其他特殊情况我只是使用以下变体,以免触及特殊链接:

(function($) 

    $.expr[':'].external = function(obj)
        return (obj.hostname != location.hostname) && obj.href.startsWith("http");
    ;

    $('a:external').attr('target', '_blank');

) (jQuery);

【讨论】:

以上是关于如何仅将 target="_blank" 自动添加到外部链接?的主要内容,如果未能解决你的问题,请参考以下文章

不知道如何在代码中使用 target="_blank"

Windows 8 应用 WebView 捕获事件 target="_blank"

如何在反应中添加 target=_blank

我可以在 Markdown 中创建带有 'target="_blank"' 的链接吗?

WKWebView 未打开 SOME target="_blank" 链接

jQuery:使用 target="_blank" 转到 URL