首页 > 解决方案 > 使用 vanilla JS 将 rel="noopener noreferrer nofollow" 添加到所有外部链接的最佳方法

问题描述

问题

我正在使用 Django 来呈现包含<a>标签的 html 模板。我想添加rel="noopener noreferrer nofollow"到所有外部链接。现在一种方法是在所有模板上手动执行此操作,或者引入一个自定义标记,其中包含检查 url 并将属性附加到锚标记的逻辑。当我们显示动态生成的也可以是外部的 url 链接时,问题就来了。为了覆盖所有链接,有一些方法可以在客户端添加此属性。

解决方案 1

我试图获取所有锚点 DOM 元素并检查它们href是内部的还是外部的。如果是外部的,请添加rel属性。

function setRelAttribute() {
    var elems = document.body.getElementsByTagName('a');
    for (var i = 0; i < elems.length; i++) {
        var elem = elems[i]
        var re = /mydomain.com/
        var isInternal = re.test(elem.href)
        if (!isInternal) {
            elem.rel= 'noopener noreferrer nofollow'
        }
    }
}

document.addEventListener('DOMContentLoaded', function () {
    setRelAttribute()
}, false);

这将在开始时执行,但只会影响预渲染的锚标记。

解决方案 2

另一种选择是创建一个全局事件侦听器,它侦听点击,然后我们检查点击了哪种元素。

document.addEventListener('click', function (event) {
    var t = event.target;
    if (t.nodeName !== 'A') {
        return
    }
    ...
})

这两种方法有什么缺点吗?

标签: javascript

解决方案


您可能最好只编写一个简单的选择查询,如下所示:

const anchors = document.querySelectorAll( 'a[href^="http"]:not([href*="example.com"])' )

这将选择所有以a开头的元素http(所以不要在本地选择相对路径)并且不包含example.com. 然后简单地将其应用于所有:

anchors.forEach(anchor => anchor.setAttribute( 'rel', 'noopener noreferrer nofollow'));

您的第一种方法仍然选择本地路径(如/images/),但这些路径不会转到外部站点。您的第二种方法会让人感到困惑,因为没有简单的方法可以知道此方法正在处理点击。如果您的元素点击事件侦听器附加到文档,我发现很容易混淆。浏览器已经在计算点击的位置和内容了,所以好好利用它吧!

当然,您可以将整个事情包装在一个DOMContentLoadedpageshow事件中:

document.addEventListener( 'DOMContentLoaded', event => {

    document.querySelectorAll( 'a[href^="http"]:not([href*="example.com"])' ).forEach(anchor => anchor.setAttribute( 'rel', 'noopener noreferrer nofollow' )); 

});

document.addEventListener( 'DOMContentLoaded', event => {
    
  document.querySelectorAll( 'a[href^="http"]:not([href*="example.com"])' ).forEach(anchor => { 
  
      anchor.setAttribute( 'rel', 'noopener noreferrer nofollow' );
      
  });

});
a { padding: 20px; }
a[rel]:after { content: ' (has [rel] attribute)'}
<a href="https://google.com/query">External</a>
<a href="/">Internal</a>
<a href="http://example.com/query">My Domain</a>


推荐阅读