一、hash模式
地址栏 URL 中的 # 符号。比如这个 URL:http://www.ittest.com/#/hello,hash 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
二、history模式
利用了 html5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
hash和history这两个方法有个共同的特点:当调用他们修改浏览器历史记录栈后,虽然当前 URL 改变了,但浏览器不会立即发送请求(the browser won’t attempt to load this URL after a call to pushState()),这就为单页应用前端路由“更新视图但不重新请求页面”提供了基础
三、hash和history两种模式比较
在一般场景中,hash模式与history模式是差不多的,但几乎所有的文章都推荐使用history模式,理由是:"#" 符号太丑
但是,history存在一个问题:
hash模式仅改变hash部分的内容,而hash部分是不会包含在HTTP请求中的:
所以在hash模式下,当 URL 改变时,页面不会重新加载
http://ittest.com/#/user/id // 如重新请求只会发送http://ittest.com/
而在history模式下,URL 就是正常的 URL(建议:前端路由 URL 和后端保持一致)
http://ittest.com/user/id
在此情况下重新(刷新F5)向后端发送请求,如后端没有配置对应/user/id的路由处理,则会返回404错误。
避免出现404错误的方法,可以用服务端路由匹配url,并在没有匹配到路由时返回404,给出个404页面。