关于URL中'?'和'#'的作用和历史


0.考考你

  请观察下面几个URL

  http://www.xxx.com/page?a=1&b=2

  http://www.xxx.com/page#xxx

  http://www.xxx.com/#/page?a=1&b=2

  http://www.xxx.com/?a=1&b=2#/page?c=3

 

  提问

  - '?'是什么意思?

  - '&'是什么意思?

  - '#'是什么意思?

  - 第一个和第三个URL有什么区别?

  - 第四个URL是什么意思?

 

  也许前两个问题你可以脱口而出地回答上来,但后面的问题你不一定能答出来,如果你没法回答,或者即使知道答案但还是不太懂原理,感觉似懂非懂,那么请阅读这篇文章。本文将详细介绍上面那些符号的意义,以及他们的演变历史,下面开始!

 

1.什么是'?'和'&'

  首先来讲讲'?''&',大家都知道,这是URL参数,一般英文叫"query string",直译也叫"查询字符串"。我们都知道"http://www.xxx.com/page"一般是指向一个页面的地址,而URL参数则是给这个页面添加了访问参数,例如我们可以在页面地址后面加上"?id=aaa&group=bbb"来记录当前需要访问的记录id为aaa,分组id为bbb。完整示例如下:

  http://www.xxx.com/page?id=aaa&group=bbb

 

  由'?'和'&'表示的URL参数从最初提出一直到现在,其作用和用法始终没有变过,而'#'则在web发展的漫长的岁月中前前后后改变过了多次。下面我们来详细讲讲'#'

 

2.'#'最初被提出时的作用

  '#'的名字为hash,最初被提出时被用于锚点定位功能。所谓锚点定位,意思是让浏览器定位到页面上的某个元素位置处。例如,某页面上有很多很多的元素,其中有一个元素的id为"div1",那么,我们只要在URL地址里加上"#div1"就可以让浏览器滚动到这个元素的位置处。示例如下:

  http://www.xxx.com/page#div1

  

  锚点定位功能不单单只在页面打开时会生效,还可以动态生效,比如你可以先在地址栏上使用"#div1"定位到div1的位置处,然后再手动修改地址栏改成"#div2",敲下回车,浏览器就能定位到div2的位置处。

 

  Try it yourself ! 自己动手试试!

  - 打开这个地址https://www.rplugin.com/demos/demo1#section3

  - 在浏览器地址栏中把"section3"改成"section8",敲回车

  你将看到的效果是,当你首次打开上面的地址时,页面默认滚动到了第3章,而当你修改了地址栏中的hash值时,页面又滚动到了第8章。

  请注意这里有一个细节!当你把"section3"改成"section8",敲回车时,页面没有重载动作,而只是做了滚动动作

  

  下面我们再来看URL参数在变更时又是什么效果

  - 打开这个地址https://www.rplugin.com/demos/demo1?id=aaa

  - 在浏览器地址栏中把"aaa"改成"bbb",敲回车

  你应该注意到了,在你敲下回车的时候,浏览器出现了loading效果,这意味着浏览器去重新加载了这个网页

  看到这里,你应该发现了URL参数和hash参数的本质区别之一,URL参数的变更会引起浏览器重新加载网页,而hash参数的变更则不会

 

  '#'在经过了一些年的发展之后,开始有了js事件支持。以IE为例,从IE8开始,IE支持onhashchange事件,每当浏览器检测到地址栏中的hash值发生了变更,就会触发一次onhashchange事件。通过这个事件,开发者可以开发出基于hash值变更的高级功能。

 

3.由'#'的特性而引申的新用法

   2008年,W3C提出了XHR的概念,通过使用XHR的api,人们发明出了ajax技术,使前端能够实现页面无刷新技术,即在页面不刷新的情况下,更新页面上的部分数据。例如,某个列表页面带有分页,首次打开页面时,js通过ajax加载并展示了第一页的数据,当用户点击第二页时,js再次发起请求加载得到第二页的数据,然后把table中原来的数据清空,重新展示第二页的数据,这样实现了整个页面不需要重新加载即可翻页动态加载浏览数据。

 

  前端页面无刷新技术的出现,是前端发展的一个历史性的进步,在后来的几年时间里,页面无刷新技术开始疯狂盛行,时至今日,该技术毫无疑问已经成为了前端技术的基石之一。而在前一小节我们讲到,hash参数的变更不会引起页面重新加载,这岂不是正好迎合了前端无刷新技术的思想么?于是'#'就自然而然地开始被大家应用到了各种页面无刷新场景。

 

  人们发现,跟在'#'后面的内容不一定非得是一个元素的id,它可以是任何字符串,我们可以在'#'后面添加任意想要的字符串,以用来记录想要存储的信息,比如当前页码等。

 

  还是以表格分页为例,我们可以人为地规定,"#page=1"表示查看第1页的数据,"#page=5"表示查看第5页的数据,以此类推。首次打开页面时,我们先看url中有没有hash参数,有则加载指定页的数据,没有则加载第1页的数据。当我们点击分页上的第5页时,我们用js把hash修改成"#page=5"。同时,我们事先定义好onhashchange事件,每当发现hash中的page改变了,我们就使用ajax去加载重新渲染新的页的数据。这样做的好处是,A用户在逛网站,如果他逛到了第5页,发现一个有趣的东西,想要分享给B用户时,A用户可以直接复制当前URL地址,比如"www.xxx.com/list#page=5",而B用户打开该地址时,就能够直接看到第5页的数据。

 

  通过上面的例子我们可以看到,通过使用hash参数,我们可以给页面任意增加想要的参数信息,参数的格式完全由我们自己定义,并且这些参数信息可以在页面无刷新的情况下动态变更;同时,将携带了hash参数信息的地址分享给其他用户时,其他用户也可以得到这些页面参数信息,以使分享者和被分享者看到的页面状态一致。这便是'#'在页面无刷新技术出现后,引申出来的新用法

 

4.更多现代框架把'#'玩出了新花样

  近十年来,前端开始出现了各种新式的MVC、MVM、MVVM框架,他们的出现为前端开发的设计思想做出了巨大贡献,与此同时,这些框架也利用hash参数实现了自己的框架功能,也算是把hash给玩出了新花样

 

  以Vue为例,Vue在构建单页面应用SPA时,使用了虚拟路由功能来模拟页面切换,而虚拟路由功能则正是利用了hash来实现的。我们先来看看Vue路由中几个典型的URL示例:

  http://www.xxx.com/#/

  http://www.xxx.com/#/page

  http://www.xxx.com/#/page?a=1&b=2

 

  上面第一个示例表示虚拟路由中的根目录,第二个示例表示虚拟路由中的某个页面,第三个示例表示某个页面带有参数,请注意,第三个示例中的"?a=1&b=2"都是在'#'的后面,他们并不是真正的URL参数,而是hash参数中的一部分,只是格式跟标准URL参数一致而已,他们是虚拟的URL参数

  可以看到,Vue把整个hash参数都用来模拟URL路径了,包括原始的URL参数也都一起模拟了。利用hash的页面无刷新特性和onhashchange事件,Vue实现了动态路由切换展示不同页面的效果。

 

5.结语

  '?'为URL参数,'#'为hash参数,前者很简单没什么花头,而后者由于本身的特性,被广大开发者和框架玩出了各种花样。通过前面的详细介绍,想必此刻的您已经对他们有了比较深入的了解。

  现在回到本文的最开头,看看那些问题你都能自信地回答上来没^_^

  最后的最后,再给你提一个问题,'?'和'#'哪个优先级高?可以自己动手测试下哦^_^


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM