javascript - 使用 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
}
...
})
这两种方法有什么缺点吗?
解决方案
您可能最好只编写一个简单的选择查询,如下所示:
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/
),但这些路径不会转到外部站点。您的第二种方法会让人感到困惑,因为没有简单的方法可以知道此方法正在处理点击。如果您的元素点击事件侦听器附加到文档,我发现很容易混淆。浏览器已经在计算点击的位置和内容了,所以好好利用它吧!
当然,您可以将整个事情包装在一个DOMContentLoaded
或pageshow
事件中:
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>
推荐阅读
- ruby-on-rails - Ruby - Airbourne Rspec API 测试
- javascript - npm 错误!找不到模块'./access-error.js'
- android - 使用 lambda forEach Kotlin 遍历列表
- graphics - 碰撞检测的特例
- jupyter-notebook - jupyterhub 上的 Jupyterlab
- filesystems - 硬盘坏了
- java - Spring Boot Security & Vaadin 页面导航&渲染问题
- python-3.x - 如果字符串出现在数据框中,则增加一列
- c# - 创建没有外键的导航属性
- sql - SQL Server 不会将触发器事务回滚到保存点