路由模式的区别
前端路由原理?两种路由的实现方式有什么区别?
1.一般比较
hash
history
abstract
前端路由主要应用在SPA(单页面开发)项目中。在无刷新的情况下,根据不同的URL来显示不同的组件或者内容。
1.hash模式
www.test.com/#/就是 Hash URL,当#后面的哈希值发生变化时,可以通过hashchange事件来监听到 URL 的变化,从而进行跳转页面,并且无论哈希值如何变化,服务端接收到的 URL 请求永远是www.test.com。Hash 模式相对来说更简单,并且兼容性也更好。每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。
2.history模式
History模式是HTML5 新推出的功能,主要使用history.pushState和history.replaceState改变 URL。通过 History 模式改变 URL 同样不会引起页面的刷新,只会更新浏览器的历史记录。当用户做出浏览器动作时,比如点击后退按钮时会触发popState事件。
*popstate 事件*
当用户点击浏览器的「前进」、「后退」按钮时,就会触发popstate事件。你可以监听这一事件,从而作出反应。
这里e.state就是当初pushState时传入的第一个参数,state 对象可以是任何可以序列化的东西。由于火狐会将这些对象存储在用户的磁盘上,所以用户在重启浏览器之后这些state对象会恢复。
*replaceState 方法*
有时,你希望不添加一个新记录,而是替换当前的记录(比如对网站的 landing page),则可以使用replaceState方法。这个方法和pushState的参数完全一样。
history.pushState() 和 history.replaceState()这两个API都有三个参数,分别是:
*a. 状态对象(state object)* — 一个JavaScript对象,与用 pushState() 方法创建的新历史记录条目关联。无论何时用户导航到新创建的状态,popstate 事件都会被触发,并且事件对象的state 属性都包含历史记录条目的状态对象的拷贝。
*b. 标题(title)* — FireFox 浏览器目前会忽略该参数,虽然以后可能会用上。考虑到未来可能会对该方法进行修改,传一个空字符串会比较安全。或者,你也可以传入一个简短的标题,标明将要进入的状态。
*c. 地址(URL)* — 新的历史记录条目的地址。浏览器不会在调用 pushState() 方法后加载该地址,但之后,可能会试图加载,例如用户重启浏览器。新的 URL 不一定是绝对路径;如果是相对路径,它将以当前 URL 为基准;传入的 URL 与当前 URL 应该是同源的,否则,pushState() 会抛出异常。该参数是可选的;不指定的话则为文档当前 URL。
两个API对比:
相同之处: 是两个 API 都会操作浏览器的历史记录,而不会引起页面的刷新。
不同之处在于: pushState 会增加一条新的历史记录,而 replaceState 则会替换当前的历史记录。
2.延伸以及扩展问题
两种路由模式的区别
1.Hash 模式只可以更改 # 后面的内容,History 模式可以通过 API 设置任意的同源 URL
2.History 模式可以通过 API 添加任意类型的数据到历史记录中,Hash 模式只能更改哈希值,也就是字符串
3.Hash模式下, 多次刷新为通一个页面的话,记录只添加一次
4.Hash 模式无需后端配置,并且兼容性好。History 模式在用户手动输入地址或者刷新页面的时候会发起 URL 请求,后端需要配置 index.html 页面用于匹配不到静态资源的时候
3项目中体现经验的点
当使用HTML5 history,刷新页面时会出现404。是因为当前url服务端无法找到,所以,要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。同时需要在前端这边处理404。
hash模式
<body>
<a href="#/">首页</a>
<a href="#/home">主页</a>
<a href="#/list">列表</a>
<div id="box"></div>
</body>
<script>
class Route{
constructor({routes}) {
let box=document.getElementById("box");
this.routes=routes;
this.init()
this.events={};
this.routes.forEach((item,i)=>{
this.events[item.path]=function(){
box.innerHTML=item.component;
}
})
}
init(){
window.addEventListener("hashchange",this.updateVide.bind(this));
}
updateVide(){
//console.log(this.events[path])
let path=window.location.hash.slice(1)
this.events[path]()
}
}
new Route({
routes:[
{
path:"/",
component:"首页"
},
{
path:"/home",
component:"主页"
},
{
path:"/list",
component:"列表"
}
]
})
</script>
history模式
<body>
<a href="javascript:;" data-to="/">首页</a>
<a href="javascript:;" data-to="/home">主页</a>
<a href="javascript:;" data-to="/list">列表</a>
<div id="box"></div>
</body>
<script>
class Route{
constructor({routes}) {
this.routes=routes;
this.initHistory();
this.init()
}
initHistory(){
console.log(window,"1111")
window.addEventListener("popstate",()=>{
console.log(window.location,'kkkk')
this.updateView(window.location.pathname)
})
}
init(){
let as=document.querySelectorAll("a");
let _this=this;
[].forEach.call(as,(item)=>{
item.onclick=function(){
let path=item.getAttribute("data-to");
//{}其实就是路由传递的一些信息,比如query,search这些
//null,是想要修改的html标签
//path才是路由地址
window.history.pushState({},null,path);
_this.updateView(path);
}
})
}
updateView(path){
let box=document.getElementById("box") box.innerHTML=this.routes.filter(item=>item.path===path)[0].component
}
}
new Route({
routes:[
{
path:"/",
component:"首页"
},
{
path:"/home",
component:"主页"
},
{
path:"/list",
component:"列表"
}
]
})
</script>
*获取千锋教育学习视频资料+源码笔记 ,进学习交流群
请添加下方微信(备注CSDN推荐)
相关文章
- Vue3.0实现todolist之路由传参(query模式传参和params传参)
- 折腾路由--Padavan私有云
- react-router-middleware-plus开源啦 | 基于react-router v6的零成本式路由权限解决方案
- 路由懒加载模式「建议收藏」
- 配置静态路由,动态路由,默认路由模式_默认路由为网络和掩码
- 原生JS实现哈希路由
- 一个网络系统,哪有那么多动态路由,基本上都是静态路由!
- 策略路由功能基本配置和测试
- TP6.0 隐藏多应用模式路由中的应用名
- Linux下配置静态路由(静态路由linux)
- 安装Linux安装路由器的步骤(linux加路由的)
- Linux系统下增加默认路由的方法(linux增加默认路由)
- 器Linux下设置路由器的指南(.linux加路由)
- Linux下实现策略路由的实战攻略(策略路由linux)
- Linux下追踪路由命令实战指南(linux追踪路由命令)
- Web 工具 MANRS Observatory 发布:可监测网络路由安全
- 利用Redis提升请求路由效率(redis 请求路由)