1 hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
hash即浏览器url中#后面的内容,包含#。hash是URL中的锚点,代表的是网页中的一个位置,单单改变#后的部分,浏览器只会加载相应位置的内容,不会重新加载页面。
- 即#是用来指导浏览器动作的,对服务器端完全无用,HTTP请求中,不包含#。
- 每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置。
- Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据。
2 history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.abc.com/book/id。如果后端缺少对 /book/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”
在不刷新整个页面的情况下修改站点的URL,就是利用 history.pushState API 来完成 URL 跳转而无须重新加载页面;
3 结合自身例子,对于一般的 Vue + Vue-Router + Webpack + XXX 形式的 Web 开发场景,用 history 模式即可,只需在后端(Apache 或 Nginx)进行简单的路由配置,同时搭配前端路由的 404 页面支持。
由于hash模式会在url中自带#,如果不想要很丑的 hash,我们可以用路由的 history 模式,只需要在配置路由规则时,加入"mode: 'history'",这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
有时,history模式下也会出问题:
eg:
hash模式下:xxx.com/#/id=5 请求地址为 xxx.com,没有问题。
history模式下:xxx.com/id=5 请求地址为 xxx.com/id=5,如果后端没有对应的路由处理,就会返回404错误;
为了应对这种情况,需要后台配置支持:
在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
hashchange事件
从The HashChangeEvent interface可以看到hashchange事件的参数HashChangeEvent继承了Event,仅仅多了两个属性
- oldURL 先前会话历史记录的URL
- newURL 当前会话历史记录的URL
简单的调用方式
window.onhashchange = function(e){
console.log('old URL:', e.oldURL)
console.log('new URL', e.newURL)
}
hash | CAN I USE 上可以看到除了IE8一下和那个尴尬的Opera Mini,hashchange事件都是支持得很好。那么怎么做到兼容,用MDN的代码做个引子
function(window) {
if ("onhashchange" in window) { return; }
var location = window.location,
oldURL = location.href,
oldHash = location.hash;
setInterval(function() {
var newURL = location.href, newHash = location.hash;
if (newHash != oldHash && typeof window.onhashchange === "function") {
window.onhashchange({
type: "hashchange",
oldURL: oldURL,
newURL: newURL
});
oldURL = newURL;
oldHash = newHash;
}
}, 100);
}