- vue-router原理
- hash模式
- 实现原理
- 改变描点
- 监听描点变化
- 实现原理
- history模式
- 实现原理
- 改变url
- 监听url变化
- 实现原理
- abstract
- hash 和 history 模式有什么区别?
- url 不一样
- 原理不同
- 其他
- 总结
- 扩展 history 出现404错误
- hash模式
vue-router原理
vue-router是vue项目的重要组成部分,用于构建单页应用。
单页应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。
路由的本质就是建立url和页面之间的映射关系。
实现原理:vue-router 的原理就是更新视图而不重新请求页面
更多详细内容,请微信搜索“前端爱好者
“, 戳我 查看 。
vue-router 可以通过 mode 参数设置为三种模式:hash 模式、history 模式、abstract 模式。
hash模式
hash模式是vue-router的默认模式。
hash指的是url描点,当描点发生变化的时候,浏览器只会修改访问历史记录,不会访问服务器重新获取页面。
因此可以监听描点值的变化,根据描点值渲染指定dom。
实现原理
改变描点
可以通过location.hash = "/hashpath"
的方式修改浏览器的hash值。
监听描点变化
可以通过监听hashchange事件
监听hash值的变化。
window.addEventListener('hashchange', () => {
const hash = window.location.hash.substr(1)
// 根据hash值渲染不同的dom
})
当调用 push 时,把新路由添加到浏览器访问历史的栈顶。
使用 replace 时,把浏览器访问历史的栈顶路由替换成新路由 hash 的值(等于 url 中 # 及其以后的内容)。
浏览器是根据 hash 值的变化,将页面加载到相应的 DOM 位置。
锚点变化只是浏览器的行为,每次锚点变化后依然会在浏览器中留下一条历史记录,可以通过浏览器的后退按钮回到上一个位置。
history模式
hash模式下,url可能为以下形式:
http://localhost:8080/index.html#/book?bookid=1
上面的url中既有#又有?,会让url看上去很奇怪,因此,可以使用history模式,在此模式下,url会如下面所示:
http://localhost:8080/book/1
实现原理
改变url
H5的history对象提供了pushState
和replaceState
两个方法,当调用这两个方法的时候,url会发生变化,浏览器访问历史也会发生变化,但是浏览器不会向后台发送请求。
// 第一个参数:data对象,在监听变化的事件中能够获取到
// 第二个参数:title标题
// 第三个参数:跳转地址
history.pushState({}, "", '/a')
监听url变化
可以通过监听popstate
事件监听history变化,也就是点击浏览器的前进或者后退功能时触发。
window.addEventListener("popstate", () => {
const path = window.location.pathname
// 根据path不同可渲染不同的dom
})
abstract
不涉及和浏览器地址的相关记录。
流程跟 hash 模式一样,通过数组维护模拟浏览器的历史记录栈 服务端下使用。
使用一个不依赖于浏览器的浏览器历史虚拟管理后台
hash 和 history 模式有什么区别?
url 不一样
hash路由再地址栏URL上有“#”,而history路由没有;
原理不同
hash 是通过 hashchange
进行监听历史栈的变化,将浏览器历史记录栈的路由替换为新的 hash
,
浏览器会根据 hash 变化,将页面加载到相应的 DOM 位置
history 是通过 window.onpopstate
对地址栏进行监听 ,使用 pushState()、replaceState()
对历史记录栈修改,从而实现 url 对加载无需跳转页面。
他有一个问题就是,刷新页面会走后端路由,所以需要服务端的辅助来完成,避免 url 无法匹配到资源时能返回页面。
其他
hash支持一些低版本的浏览器,而history不支持。
总结
- hash路由在地址栏URL上有#,用
window.location.hash
读取。而history路由没有,会好看一点 - 我们进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了(
刷新是网络请求,没有后端准备时会报错
)。 - hash路由支持低版本的浏览器,而
history路由是HTML5新增的API
。 - hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。
- history运用了浏览器的历史记录栈,之前有
back,forward,go
方法,之后在HTML5中新增了pushState()和replaceState()
方法,它们提供了对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会马上向后端发送请求。 history的这种模式需要后台配置支持
。比如:当我们进行项目的主页的时候,一切正常,可以访问,但是当我们刷新页面或者直接访问路径的时候就会返回404 【那是因为在history模式下,只是动态的通过js操作window.history来改变浏览器地址栏里的路径,并没有发起http请求,但是当我直接在浏览器里输入这个地址的时候,就一定要对服务器发起http请求,但是这个目标在服务器上又不存在,所以会返回404
】
扩展 history 出现404错误
1:hash 模式下,仅hash符号之前的内容会被包含在请求中,如http://www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误。
2:history模式下,前端的URL必须和实际向后端发起请求的URL一致。如htttp://www.abc.com/book/id。如果后端缺少对/book/id 的路由处理,将返回404错误
问题解决:
出现404错误的解决办法:网上介绍的很多方法都不行。安装URL重写模块,配置重写规则,统一指向index.html.或者直接把url重写生成的web.config文件直接放置到网站根目录下即可。
参考文档
- https://v3.router.vuejs.org/zh/installation.html
- https://www.cnblogs.com/ifon/p/15881223.html
- https://zhuanlan.zhihu.com/p/584365427
- https://www.php.cn/faq/490021.html
- https://segmentfault.com/a/1190000023662742