前言
说到<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信息 |
---|---|---|
http | http/https | 完整referrer信息 |
https | https | 完整referrer信息 |
https | http | “” |
origin
发送文档的来源(协议、主机和端口)。只能获取到域名信息,即location.origin的值
来源页面
来源页面 | 跳转页面 | referrer信息 |
---|---|---|
https://dengzhanyong.com/blog?id=123 | 任意页面 | https://dengzhanyong.com |
origin-when-cross-origin
对于跨域请求,发送文档的来源。对于同源请求,发送来源、路径和查询字符串。
来源页面
来源页面 | 跳转页面 | referrer信息 |
---|---|---|
https://dengzhanyong.com/blog?id=123 | https://dengzhanyong.com/about | https://dengzhanyong.com/blog?id=123 |
https://dengzhanyong.com/blog?id=123 | https://baidu.com | http://dengzhanyong.com |
https://dengzhanyong.com/blog?id=123 | http://dengzhanyong.com | https://dengzhanyong.com/blog?id=123 |
same-origin
对于同源请求,发送引用页信息。对于跨域请求,不发送引用页信息。
来源页面 | 跳转页面 | referrer信息 |
---|---|---|
https://dengzhanyong.com/blog | https://dengzhanyong.com/about | https://dengzhanyong.com/blog |
https://dengzhanyong.com/blog | https://baidu.com | “” |
strict-origin-when-cross-origin
如果协议安全级别保持不变或更高(HTTP 到 HTTP、HTTPS 到 HTTPS 以及 HTTP 到 HTTPS 都可以),则发送来源。对于较不安全的级别(从 HTTPS 到 HTTP),则不发送任何内容。(2020年之后为默认值)
来源页面 | 跳转页面 | referrer信息 |
---|---|---|
https://dengzhanyong.com/blog | https://dengzhanyong.com/about | https://dengzhanyong.com/blog |
https://dengzhanyong.com/blog | https://dengzhanyong.com | https://dengzhanyong.com |
https://dengzhanyong.com/blog | https://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>等不含特定行为的标签作为容器,让后为其绑定相应的点击事件来实现跳转。
写在最后
欢迎加入前端筱园交流群:
关注我的公众号【前端筱园】,不错过每一篇推送