对document.referrer的理解
1.document.referrer
最近有个需求需要实现一个功能,需要判断用户是从A页面扫码进来的B页面,还是直接在地址栏中输入B页面的的链接进来。当时第一个想到的就是document.referrer。
javascript 有一个可以获取前一页面的URL地址的方法:document.referrer
document.referrer 的来源
- referrer 属性可返回载入当前文档的文档的 URL, 如果当前文档不是通过超链接访问的,那么当前文档的URL为NULL,这个属性允许客户端的 javascript 访问 HTTP 头部;
- referrer 属性,我们可以从 http 头部获取
document.referrer 的兼容性
document.referrer IE7都支持,它的兼容性比较高,Android 5.0开始支持,iOS都支持,PC端浏览器从IE7就开始支持了,兼容性没有什么大的问题。
2、使用场景
从使用意义上来说document.referrer希望能够追踪到的是浏览器端行为。如果B页面被打开,那么浏览器端可能会发生的动作有用户操作、JS代码两种。
先来看看用户打开页面A可能会进行的操作:这里的link即指标签
1 | 直接在地址栏中输入A的地址 |
---|---|
2 | 从A页面左击link B,跳转至A页面 |
3 | 从A页面左击link B,在新窗口中打开 |
4 | 从A页面左击link B,在新标签页中打开 |
5 | 拖动link A至地址栏 |
6 | 拖动link A至标签栏 |
7 | 使用浏览器的前进、后退按钮 |
JS打开页面可能的方式:
1 | 修改window.location |
---|---|
2 | 使用window.open |
上面列出了客户端打开页面的一些方法,此外,如果通过服务端的重定向技术,也能够使得页面A呈现给访客。
下面来针对具体的浏览器测试,如果是上述的这些情况,document.referrer表现如何:
序号 | 场景 | IE8.0 | FF3.6 | FF4.0 | chrome |
---|---|---|---|---|---|
1 | 直接在地址栏中输入B的地址 | “ “ | “ “ | “ “ | “ “ |
2 | 从A页面左击link B,B页面替换A页面(target=’_self’) | √ | √ | √ | √ |
3 | 从A页面左击link B,B在新窗口中打开(target=’_blank’) | √ | √ | √ | √ |
3 | 从A页面右击link B,在新窗口中打开 | √ | √ | √ | “ “ |
4 | 从A页面右击link B,在新标签页中打开 | √ | √ | √ | “ “ |
5 | 鼠标拖动link B至地址栏 | / | “ “ | “ “ | “ “ |
6 | 鼠标拖动link B至标签栏 | “ “ | “ “ | “ “ | “ “ |
7 | 使用浏览器的前进、后退按钮 | 保持 | 保持 | 保持 | 保持 |
8 | 修改window.location打开B页面(同域) | “ “ | √ | √ | √ |
9 | 使用window.open打开B页面 | “ “ | √ | √ | √ |
10 | 服务器重定向至B页面 | “ “ | “ “ | “ “ | “ “ |
其中,” “表示一个空的字符串,√表示能够正确判断来源页,保持则意味使用前进后退不会改变页面的referrer。从这张表里可以看出document.referrer能覆盖大约一半的case。但是对于一些比较常用的操作,例如利用鼠标拖动link至标签栏、前进后退等情况还不能做出正确的处理。
3,无法获取 referrer 信息的情况
下面的场景无法获得 referrer 信息:
直接在浏览器中输入地址
使用
location.reload()
刷新(location.href
或者location.replace()
刷新有信息)在微信对话框中,点击进入微信自身浏览器
扫码进入微信或QQ的浏览器
直接新窗口打开一个页面
从https的网站直接进入一个http协议的网站(Chrome下亲测)
a
标签设置rel="noreferrer"
(兼容IE7+)meta
标签来控制不让浏览器发送referer
<meta content="never" name="referrer">
点击 flash 内部链接
Chrome4.0以下,IE 5.5+以下返回空的字符串
使用 修改 Location 进行页面导航的方法,会导致在IE下丢失 referrer,这可能是IE的一个BUG
跨域
4.结束语
因为最终的使用场景中,从A页面扫码进入B页面的过程中,后端小哥哥做了302重定向跳转到B页面,这时候在B页面获取到的document.referrer
也是""
。