原始时代路由
路由全部都是由服务端控制的,前端代码和服务代码过度融合在一起。
客户端/前端发起http请求,服务端通过不同的url路径去匹配不同的路由/返回不同的数据
优点:直接返回一个html文档,渲染页面结构。SEO效果很好,首屏时间快
缺点: 前端代码和服务代码融合在一起,开发协同非常混乱。服务器压力大,因为把构建html的工作放在服务端。
单页面应用
所谓的单页面是指只有一个html 文档。
特点:
- 页面中的交互是不刷新页面的,比如点击按钮,比如点击出现一个弹窗
- 多页面间的交互不需要刷新页面,比如跳转
- 加载过的公共资源无需重复加载
- 不同url 会渲染不同内容
Hsah 与History
- 直观上看 hash路由有#,history 路由没有
- hash 的#部分内容不会给服务端,history 路由的所有内容都会给服务端
- hash 通过hashchange 监听变化,history 通过 popstate 监听变化
Hsah
特点
- url 中带有#号, # 后面的部分不会传递给服务端
举个例子 www.XXX.com/#/uder/xiaoming 服务器只能拿到 www.XXX.com/ - hash 值得更改不会导致页面刷新
location.hash = '#user' 改为 location.hash = '#home'
html 文档不会刷新 - hash 值得更改,会在浏览器的访问历史中添加一条记录,所以我们才可以通过浏览器的返回、前进按钮来控制hash的切换
- hash 值得更改会触发hashchange 事件
location.hash = '#user' 改为 location.hash = '#home' 可以通过
window.addEventLisenter('hashchange',()=>{})监听
如何更改hash
- location.hash="#xiaoming"
- html 标签样式 <a href="#xiaoming" >点击跳转到xiaoming</a>
html5 history
window.history.back() // 后退
window.history.forward() // 前进
window.history.go() // 可传一个number ,正值前进 负值后退
window.history.pushState(null,null,null)
window.history.replaceState(null,null,null)
pushState/replaceState 的参数
- state 是一个对象与指定网址相关,当popstate 事件触发的时候该对象会传入回调函数
- title 新页面的标题,浏览器支持不一,null
- url 页面新地址
History 的特性
pushState时会触发popState 吗?
- 没有#
- pushState/replaceState 并不会触发 popstate 事件, 这时我们需要手动触发页面的重新渲染。
- 我们可以使用 popstate 来监听 url 的变化
- popstate 到底什么时候才能触发。
4.1 点击浏览器后退按钮
4.2 点击浏览器前进按钮
4.3 js 调用 back 方法
4.4 js 调用 forward 方法
4.5 js 调用 go 方法
手写一个hashRouter 简易版
class BaseRouter{
constructor(){
this.routes = {}
this.refresh = this.refresh.bind(this);
window.addEventListener('load', this.refresh);
window.addEventListener('hashchange', this.refresh);
}
router(path,callback){
this.routes[path] = callback || function(){}
}
refresh(){
const path = `/${location.hash.slice(1) || '' }`
this.routes[path]();
}
}
let body = document.querySelector('body')
function changeBgColor(color){
body.style.backgroundColor= color
}
const Router = new BaseRouter()
Router.router('/',function(){
changeBgColor('white')
})
Router.router('/green',function(){
changeBgColor('green')
})
Router.router('/gray',function(){
changeBgColor('gray')
})
手写一个historyRouter 简易版
class BaseRouter{
constructor(){
this.routers = {}
this.init(location.pathname)
this._bindPopState()
}
init(path){
window.history.replaceState(path,null,path)
const cb = this.routers[path]
cb && cb()
}
router(path,callback){
this.routers[path] = callback || function(){}
}
_bindPopState(){
window.addEventListener('popsate',(e)=>{
const path = e.state && e.state.path
this.routers[path] && this.routers[path]()
})
}
go(path){
window.history.pushState({path},null,path)
const cb = this.routers[path]
cb && cb()
}
}
let body = document.querySelector('body')
const container = document.querySelector('.container');
function changeBgColor(color){
body.style.backgroundColor= color
}
const Router = new BaseRouter()
Router.router('/',function(){
changeBgColor('white')
})
Router.router('/green',function(){
changeBgColor('green')
})
Router.router('/gray',function(){
changeBgColor('gray')
})
container.addEventListener('click',(e)=>{
if(e.target.tagName === 'A'){
e.preventDefault()
Router.go(e.target.getAttribute('href'))
}
})
historyRouter 需要后端配合,将路由映射地址改为index.html
网友评论