前言

说到<a>标签,对于一个前端开发来说应该算是最基础的标签之一了,绝大多数情况都是用来做链接跳转,使用href 配置跳转地址,再设置 target="_blank"在新标签页打开。
但是<a>标签的功能远远不止于此,它可以实现很多看似复杂的功能,例如:SEO优化、无感刷新主页面、PV统计、避免重复打开新窗口等。

<a>标签还有很多平时不常用的属性,只是你没有去了解过,当你知道这些属性后,你会发现它们可以解决很多实际的业务问题。不只是<a>标签,其他标签也一样,每个属性和属性值肯定都有它存在的意义,肯定会有一些符合其使用的场景。

欢迎访问本人个人网站:https://www.dengzhanyong.com

关注公众号【前端筱园】,不错过每一篇推送。

加入【交流群】,共同学习成长

rel属性

规定当前文档和被链接文档之间的关系。它的属性值有很多,这里列举几个需要重点关注的几个值。

nofollow

这个属性值跟SEO有关。
什么是SEO?

SEO是一种利用搜索引擎规则,来提高网站在搜索引擎结果页(SERP)中的自然排名的方法。SEO的目的是吸引更多的有机流量,提高网站的可见性和曝光度,从而增加品牌知名度和潜在客户数量。

当rel的值为nofollow时,就是告诉搜索引擎不需要追踪这个链接,SEO有个策略,如果一个权重很高的网站,直接外链一个权重不高的网站,那么被链接的网站权重有一定概率被提高,从而会刮分原网站的权重,以下两种情况需要设置 rel="nofollow"

  • 目标页面显示的是无效信息,或者包含敏感信息
  • 目标页面不属于本站子页面,属于外站页面,不希望共享权重

不知道你以前有没有注意到那些社区、新闻、知识分享等大型平台,在点开文章中的链接时,并不会直接跳转到目标页面,而总是先跳转到一个中转页(不知道大家以前有没有想过为什么要这么做)。

在这里插入图片描述

打开控制台检查元素,可以看到其实是做了双重优化,首先是设置rel="nofollow",防止权限被外泄。

其次是href的链接是中转页面,目标页面地址作为参数,这样既是链接被跟踪后,权重也是被分到本网站的其他页面,不会流向第三方网站。(谷歌现在使用了一种新的分配规则,既是设置了链接不允许被跟踪,但也有一定概率会被分配权重)
在这里插入图片描述

noopener & opener

假如有这样一个业务场景,主页面点击链接打开一个新增人员信息的页面,当子页面填写完信息提交后,希望主页面自动刷新展示最新数据。一般有两种方式:

  • 使用postMessage跨页面通信,当提交表单后,通知主页面刷新数据
  • 使用visibilitychange事件,监听主页面显示状态变为visible时,刷新数据

这两种方式都可以实现这个需求,但是都不够优雅,第一种需要更高的成本,第二种数据更新存在滞后性。

通过<a>标签的设置rel="opener"可以实现优雅的无感更新。

<a href="/create.html" target="_blank" rel="openner">
  新建人员信息
</a>

设置了rel="opener"后,在子页面可以通过 window.opener拿到主页面的window对象,在主页面中可以把数据更新的方法挂在到window上,当子页面提交数据后,执行主页面的更新方法就可以无感更新数据。

 window.opener.updatedate();

但是这种方式也有弊端,就是安全问题,因为window的权限太高了,任何挂载到window上的属性和方法都可以被执行,包括document。如果是链接到危险网站,可以通过window.opener.document.cookie获取用户的敏感信息进行身份伪造,甚至可以恶意篡改主页面的内容。

在2020年以前,设置target="blank"的链接元素默认为opener,需要手动的设置rel="noopener"来避免这个安全隐患。但是即使在2020以后,IE浏览器和Edge浏览器(非chromium渲染内核的Edge浏览器)依旧存在此安全隐患问题,因此在日常业务开发中,最好主动设置rel="noopener"属性,除非子页面是你信任的页面。

当设置rel="noopener"后,子页面window.opener的值为null。

referrer&noreferrer

在未设置的情况下,默认值为referrer,使用document.referrer可以获取到当前页面的来源。例如通过百度打开的一个网站,在控制台输出document.referrer的值:
在这里插入图片描述

如果是直接输入网址打开的网页,document.referrer的值为空字符串。

那些知名的网站分析工具,例如百度统计、Google Analytics,都是通过document.referrer来统计PV的,这有利于帮助我们了解不同渠道的客户占比,有利于对市场的趋势进行分析并进行合理的调整。
在这里插入图片描述
在这里插入图片描述

在日常的业务开发中,也可以利用document.referrer来实现一些业务需求,例如:

按钮显示返回还是首页

很多详情或者编辑页面都会有返回按钮,如果是通过第三方链接或者直接打开的页面,这种情况下没有上一页,显示“返回”就显得很奇怪,显示成“主页”更符合业务场景。此时就可以通过document.referrer判断来源是外部还是内部跳转。

返回定位

同样是进入详情页面,如果通过主页进入的详情,详情页面点击返回按钮回到主页面时,希望可以滚动到进入详情页面前的位置。

通常通过在URL上添加参数来实现:

// 详情页返回
<a href="/index.html?from=detail">返回</a>
// 其他页面进入
<a href="/index.html">首页</a

使用document.referrer可以更优雅的判断进入页面的来源。

什么时候使用"noreferrer"?

在本站范围内的链接,建议不要设置noreferrer,因为会影响页面来源的追踪,不利于用户相关数据的统计。

对于外站的链接,建议都设置"noreferrer",因为URL中包含了地址信息,以及其他的参数信息,外站可能利用这些信息去做一些坏事。

隐私保护和信息传播问题
但是对于大多数的社交媒体类的网站来说,一般是不设置"noreferrer",因为本来就是社交开放的网站,更注重三方网站的溯源,有利于信息的传播,可以间接提高影响力和访问量。

是否设置“noreferrer”,就需要在隐私保护和信息传播之间二选一,有没有可以二者兼得的方案呢?答案是有的,那就是referrerpolicy属性。

referrerpolicy属性

该属性规定当用户单击超链接时要发送的 referrer 信息(引用者信息)。可以理解为是referrer的增强,它可以配置在什么条件下发送什么样的信息。它有以下几个值:

no-referrer

不发送引用者信息与上面的noreferrer一致,document.referrer返回空字符串。
来源页面

来源页面跳转页面referrer信息
https://dengzhanyong.com/blog任意页面“”

no-referrer-when-downgrade

如果协议安全级别保持不变或更高(HTTP 到 HTTP、HTTPS 到 HTTPS、HTTP 到 HTTPS 都可以),则发送来源、路径和查询字符串。不向安全级别较低的级别发送任何内容(HTTPS 到 HTTP 是不行的);(2020年之前为默认值,现在不是了)。

来源页面跳转页面referrer信息
httphttp/https完整referrer信息
httpshttps完整referrer信息
httpshttp“”

origin

发送文档的来源(协议、主机和端口)。只能获取到域名信息,即location.origin的值
来源页面

来源页面跳转页面referrer信息
https://dengzhanyong.com/blog?id=123任意页面https://dengzhanyong.com

origin-when-cross-origin

对于跨域请求,发送文档的来源。对于同源请求,发送来源、路径和查询字符串。
来源页面

来源页面跳转页面referrer信息
https://dengzhanyong.com/blog?id=123https://dengzhanyong.com/abouthttps://dengzhanyong.com/blog?id=123
https://dengzhanyong.com/blog?id=123https://baidu.comhttp://dengzhanyong.com
https://dengzhanyong.com/blog?id=123http://dengzhanyong.comhttps://dengzhanyong.com/blog?id=123

same-origin

对于同源请求,发送引用页信息。对于跨域请求,不发送引用页信息。

来源页面跳转页面referrer信息
https://dengzhanyong.com/bloghttps://dengzhanyong.com/abouthttps://dengzhanyong.com/blog
https://dengzhanyong.com/bloghttps://baidu.com“”

strict-origin-when-cross-origin

如果协议安全级别保持不变或更高(HTTP 到 HTTP、HTTPS 到 HTTPS 以及 HTTP 到 HTTPS 都可以),则发送来源。对于较不安全的级别(从 HTTPS 到 HTTP),则不发送任何内容。(2020年之后为默认值)

来源页面跳转页面referrer信息
https://dengzhanyong.com/bloghttps://dengzhanyong.com/abouthttps://dengzhanyong.com/blog
https://dengzhanyong.com/bloghttps://dengzhanyong.comhttps://dengzhanyong.com
https://dengzhanyong.com/bloghttps://baidu.com“”

unsafe-url

发送来源、路径和查询字符串(不考虑安全性)。请谨慎使用此值!

综上所述,要想兼得隐私保护和信息传播,推荐使用 origin-when-cross-origin ,这样既可以让外站知道来源,也可以增加曝光量。

<a href="https://www.baidu.com" 
  referrerpolicy="origin-when-cross-origin">
  外部链接
</a>

target属性

target 属性的用途是告诉浏览器希望将所链接的资源显示在哪里。默认情况下,浏览器使用的是显示当前文档的窗口、标签页或框架(iframe),所以新文档将会取代现在显示的文档,不过还有其他选择。

_preview

当属性值为_preview时,可以让新窗口采用预览模式打开,与_blank的区别是对于同一个链接永远只会打开一个新的窗口。
举个例子:

在文章列表页中,点击文章标题会新打开一个详情页,如果多次点击同一个标题,则会打开多个详情页,让人看起来眼花缭乱,也不知道哪个是最新的。设置_preview后,当详情页被打开后,再次点击只会刷新新窗口详情页,不会出现打开多个窗口的情况。

其他属性值

  • _parent

当链接位于一个内联框架 <iframe> 中时,使用 target="_parent" 会使链接在包含该 <iframe> 的父窗口中打

  • _top

如果一个文档包含多层嵌套的框架,target=“_top” 会让链接跳过所有嵌套框架,直接在最顶层的窗口打开

  • _self(默认值)

在当前窗口或标签页中打开链接

href属性

href 属性的值可以是任何有效文档的相对或绝对 URL,包括片段标识符和 JavaScript 代码段。

锚点定位

当href的值以“#”为前缀时,点击后,页面会自动滚动到锚点的位置:

<a href="#comment">
  查看评论
</a>

点击后,会跳转到id为“comment”的元素的位置,同时浏览器的URL地址的hash值会变为#comment。

锚点定位还有一个隐藏值,当值为"#top"时,会让页面滚动到顶部。

执行脚本

href的值也可以执行一段JS脚本,格式为:javascript:[脚本内容]

<a href="javascript:alert('Hello World!');">执行 JavaScript</a>

直接发送邮件

点击后直接打开邮箱发送邮件,格式为:mailto:[邮箱地址]

<a href="mailto:someone@example.com">发送电子邮件</a>

直接拨打电话

点击后直接拨打电话,格式为:tel:[电话号码]

<a href="tel:+8613888888888">+86 138  8888 8888</a>

标签嵌套

当两个<a>标签嵌套式会出现什么效果,就像下面这样。

<a href="https://www.baidu.com" target="_blank">
    前面内容
<a href="https://www.dengzhanyong.com" target="_blank">
      我的网站
    </a>
    结尾还有一些文字
</a>

当两个<a>标签嵌套时,浏览器会自动为内层的<a>标签添加结束符,导致它从外层<a>标签中被剥离出来,这样就形成了两个独立的链接而非嵌套结构
在这里插入图片描述

HTML的嵌套规则中明确指出,<a>标签不应嵌套另一个<a>标签,这种设计是为了避免由嵌套链接带来的潜在的混淆和冲突。可以改为使用<span>或<div>等不含特定行为的标签作为容器,让后为其绑定相应的点击事件来实现跳转。

写在最后

欢迎加入前端筱园交流群:
描述文字
关注我的公众号【前端筱园】,不错过每一篇推送

描述文字
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐