什么是前端路由
简单地说,就是在保证只有一个html页面,且在和用户交互时,不刷新和跳转页面的同时,为单页面(SPA)中的每个视图展示**匹配一个特殊的url,**在刷新,前进后退时都通过这个特殊的url来实现
hash模式
hash模式中的hash就是指#号及其后面的字符,比如’www.baidu.com/#hash’,其中#hash就是hash值, hash通过监听浏览器的onhashchange()事件来实现路由的变化,如果我们在window.hashChange事件中获取当前的hash值,并根据hash值来修改页面的内容,就达到了前端路由的目的,并且hash 值的变化不会导致浏览器向服务器发送请求
<body>
<!-- html:菜单中href设置为hash形式,id为app中放置页面内容 -->
<ul id="menu">
<li>
<a href="#index">首页</a>
</li>
<li>
<a href="#shop">商城</a>
</li>
<li>
<a href="#my">我的</a>
</li>
</ul>
<div id="app"></div>
<script>
//在window.onhashchange中获取hash值,根据不同的值,修改app中不同的内容,起到了路由的效果
function hashChange(e) {
console.log('hash值',location.hash)
console.log('herf值',location.href)
console.log('新路径',e.newURL)
console.log('旧路径',e.oldURL)
let app = document.getElementById('app')
switch (location.hash) {
case '#index':
app.innerHTML = '<h1>这是首页内容</h1>'
break
case '#shop':
app.innerHTML = '<h1>这是商城内容</h1>'
break
case '#my':
app.innerHTML = '<h1>这是我的内容</h1>'
break
default:
app.innerHTML = '<h1>404</h1>'
}
}
window.onhashchange = hashChange
hashChange()
</script>
</body>
history模式
history就是我们平时看到的正常的连接形式。history模式基于window.history对象的方法。相较于hash模式样式上少个#
在html4中,已经支持window.history对象来控制页面历史记录跳转,常用的方法包括:
history.forward():在历史记录中前进一步
history.back():在历史记录中后退一步
history.go(n):在历史记录中跳转n步骤,n=0为刷新本页,n=-1为后退一页
在HTML5中,window.history对象得到了扩展,新增的API包括:
history.pushState(data[,title][,url]):向历史记录中追加一条记录
history.replaceState(data[,title][,url]):替换当前页在历史记录中的信息。
history.state:是一个属性,可以得到当前页的state信息。
window.onpopstate:是一个事件,在点击浏览器后退按钮或js调用forward()、back()、go()时触发。监听函数中可传入一个event对象,event.state即为通过pushState()或replaceState()方法传入的data参数
如果用户使用浏览器的前进后退按钮,则会触发window.onpopstate事件,监听页面根据路由地址修改页面内容。
<body>
<!-- html:菜单中href设置为history形式,id为app中放置页面内容 -->
<ul id="menu">
<li>
<a href="/index">首页</a>
</li>
<li>
<a href="/shop">商城</a>
</li>
<li>
<a href="/my">我的</a>
</li>
</ul>
<div id="app"></div>
<script>
//js:
//改造超链接,阻止默认跳转,默认的跳转是会刷新页面的
document.querySelector('#menu').addEventListener('click', function (e) {
console.log('e',e);
if (e.target.nodeName === 'A') {
e.preventDefault()
let path = e.target.getAttribute('href') //获取超链接的href,改为pushState跳转,不刷新页面
window.history.pushState({}, '', path) //修改浏览器中显示的url地址
render(path) //根据path,更改页面内容
}
})
function render(path) {
let app = document.getElementById('app')
switch (path) {
case '/index':
app.innerHTML = '<h1>这是首页内容</h1>'
break
case '/shop':
app.innerHTML = '<h1>这是商城内容</h1>'
break
case '/my':
app.innerHTML = '<h1>这是我的内容</h1>'
break
default:
app.innerHTML = '<h1>404</h1>'
}
}
//监听浏览器前进后退事件,并根据当前路径渲染页面
window.onpopstate = function (e) {
render(location.pathname)
}
//第一次进入页面显示首页
render('/index')
</script>
</body>
两种模式的区别
模式 | hash模式 | history模式 |
---|---|---|
样式 | 带有#号 | 不带#号 |
加载源 | 只能修改#后面的部分,只能加载与当前同文档的url | 通过pushState设置的新的url与当前url同源的任意url |
浏览器历史栈 | 必须设置新的hash值与原来不一样才会添加到记录到历史栈中 | pushState设置的新的url,即使与当前url一模一样也会添加记录到历史栈中 |
添加到记录中的数据类型 | 只能添加短字符串 | pushState通过history.state对象可以添加任意类型的数据到记录中 |
兼容 | ie8以上 | ie10以上 |
是否需要后端配合 | 前端自己控制hash值来改变路由 | 需要后端配合将所有访问都指向index.html,负责用户刷新页面会导致404 |