vue-router
Router
路由是伴随着 SPA (单页面应用存在的)
spa出现后,前端可以自由的控制组件的渲染,来模拟页面的跳转
总结:
传统的路由一般是根据 URL 访问相关的 controller 进行数据资源的生成返回前端
前端路由是用 js 根据 url 返回对应的组件加载
所以,前端路由包含两个部分:
- url 的处理
- 组件加载
history&hash 路由
- hash 路由和 history 路由的区别:
hash 路由一般会携带一个#号,不够美观,history 路由不存在这个问题,
默认 hash 路由是不会向浏览器端发送请求,一般用于锚点,history 中 go、back、forward 以及浏览器的前进和后退按钮,一般都会向服务器端发起请求。
hash 路由不支持 SSR,history 是可以的
history 部署的时候,利用 nginx 渲染首页,然后根据路径重新跳转
hash 路由监听 一般用 onHashChange history 路由的监听一般是 onPopState
history
history 是一个 BOM api,里面有 go,forward,back 三个 API,以及 pushState、replaceState
pushState 和 replaceState 有啥区别
两者都不会触发 popState 事件,不一定会重新渲染
popState 啥时候触发:
只有在点击浏览器的前进和后退按钮,以及调用 back go 的时候会触发
vue router
动态路由,包括 react.lazy import(),是一种代码进行动态拆分的技术,一般叫做 code splitting
在需要的时候才进行加载,
路由守卫
路由守卫是在路由触发之前执行一系列的操作,next 可以继续往下执行
触发流程:
- 组件--前一个组件的 beforeRouteLeave
- 全局--router.beforeEach
- 组件--如果是路由的参数 变化,触发 beforeRouteUpdate
- 配置文件里面:下一个 beforeEnter
- 组件--内部声明的 beforeRouteEnter
- 全局调用 beforeresolve
- 全局的 router.afterEach
router-history
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>H5路由</title>
</head>
<body>
<div id="container" >
<a href='./'>首页</a>
<a href='./about'>关于我们</a>
<a href='./user'>用户列表</a>
</div>
<div id="context"></div>
</body>
</html>
<script>
class BaseRouter {
constructor(){
this.routes = {}
this._bindPopsState()
this.init();
}
init(path){
window.history.replaceState({path},null,path)
const cb = this.routes[path];
if(cb){
cb();
}
}
route(path,callback){
this.routes[path] = callback || function(){}
}
go(path){
window.history.pushState({path},null,path)
const cb = this.routes[path];
if(cb){
cb();
}
}
_bindPopsState(){
window.addEventListener('popstate', e => {
const path = e.state?.path
this.routes[path] && this.routes[path]();
})
}
}
const Route = new BaseRouter()
Route.route('./about', () => changeText("关于我们页面"));
Route.route('./user', () => changeText("用户列表页"));
Route.route('./', () => changeText("首页"));
function changeText(arg){
document.getElementById('context').innerHTML = arg;
}
container.addEventListener('click',e => {
if(e.target.tagName === 'A'){
e.preventDefault();
Route.go(e.target.getAttribute('href'))
}
})
</script>
router-hash
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>路由</title>
</head>
<body>
<div id="container" >
<button onclick="window.location.hash = '#'">首页</button>
<button onclick="window.location.hash = '#about'">关于我们</button>
<button onclick="window.location.hash = '#user'">用户列表</button>
</div>
<div id="context"></div>
</body>
</html>
<script>
class BaseRouter {
constructor(){
this.routes = {};
this.refresh = this.refresh.bind(this);
window.addEventListener('load', this.refresh);
window.addEventListener('hashchange', this.refresh);
}
route(path,callback){
this.routes[path] = callback || function(){}
}
refresh(){
const path = `/${window.location.hash.slice(1) || ''}`;
this.routes[path]()
}
}
const Route = new BaseRouter()
Route.route('/about', () => changeText("关于我们页面"));
Route.route('/user', () => changeText("用户列表页"));
Route.route('/', () => changeText("首页"));
function changeText(arg){
document.getElementById('context').innerHTML = arg;
}
</script>