Vue-router
vue-router是干什么的,为什么用vue-router,为什么不直接用url,权限控制为什么要前端控制
- 干什么的:单页应用 (SPA) 中将浏览器的 URL 和用户看到的内容绑定起来,当用户在应用中浏览不同页面时,URL 会随之更新,但页面不需要从服务器重新加载(单页面应用的特点) 通过配置路由告诉url路径来显示哪些个组件
- 为什么用vue-router:spa单页面应用实现url改变页面不刷新,有路由守卫可以实现权限管理,支持两种路由模式(hash、history)、实现管理路由跳转和嵌套等功能
- 为什么不直接用url:因为用url的话url一改变就会使得整个页面刷新,影响页面性能
vue-router实现核心
- 添加hashchange事件监听、首先创建一个Router实例,调用addroute给实例维护的一个routes对象添加路径,和回调函数,然后init,给window添加load(页面加载完毕会调用)和hashchange(hash值发生改变)事件监听,添加的事件对url中的hash值进行split并在维护的routes对象中找到对应的key,然后调用该key的对应的函数即可
不用vue-router,用原生js实现路由和路由权限
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li><a onclick="location . href='#/'">11111</a></li>
<li><a href="#/admin">22222222</a></li>
<li><a onclick="location . href='#/server'">333333333</a></li>
</ul>
<div id="div">展示</div>
<script type="text/javascript">
let res=document . getElementById("div")
const Router=function(){
this . route={}
this . curUrl=''
this . mode=''
this . addRoute=(path,cb)=>{
console . log(path);
this . route[path]=cb||function(){}
}
this . refresh=()=>{
if(this . mode='history'){
this . curUrl=location . pathname
this . route[this . curUrl]()
}else{
this . curUrl=location . hash . split('#')[1]||'/'
this . route[this . curUrl]()
}
}
this . push=(url)=>{
history . pushState({},null,url)
this . refresh()
}
this . replace=(url)=>{
history . replaceState({},null,url)
this . refresh()
}
let res=document . getElementById('div')
this . init=({mode})=>{
this . mode=mode
if(mode=='history'){
window . addEventListener("load",this . refresh,false)
window . addEventListener("popstate",this . refresh,false)
}else{
window . addEventListener("load",this . refresh,false)
window . addEventListener("hashchange",this . refresh,false)
}
}
}
const router=new Router()
const baseUrl='/node-template/src/js/easyRoute.html'
router . addRoute(baseUrl,()=>{
res . style . backgroundColor='pink'
res . innerHTML='11111'
})
router . addRoute('/node-template/src/js/history.html',()=>{
res . style . backgroundColor='black'
res . innerHTML='11111'
})
router . init({
mode:"history"
})
router . push('/node-template/src/js/history.html')
</script>
</body>
</html>
什么是路由守卫,有哪些钩子
就是在进行页面跳转前的一些钩子函数,一般可以用来进行权限判断是否放跳转或者取消
- beforeEach(全局守卫,每一次路由切换都会执行)
- beforeEnter (路由独享守卫,在路由中写的用来对特定的路由进行跳转的时候设置的守卫)
onBeforeRouteUpdate(路由改变但是当前组件不变时调用)onBeforeRouteLeave(离开时) 组件内的守卫
怎么做权限管理
- 前端来处理:meta元信息添加该路由的权限信息,在beforeEach中获取用户权限筛选生成路由数组,通过addRoute加入到路由数组和vuex或者pinia中,然后放行。
注意:假如将权限信息直接存放在sessionStorage中,会被代替和修改。
- 后端处理:直接返回路由数组然后addRoute添加即可
调用不同跳转api分别会触发哪些事件(使用了哪些原生的api)
- hash模式调用了 绑定在window上的hashchange和load事件
- history:pushState、replaceState(不会被popState监听)、go、forward、back=>受popState监听(监听历史记录的变化,一旦变化就触发回调函数)
- 注意:history.go histroy.forward默认也是调用popState方法
vue-router的两种模式,他们的区别
history模式和hash模式
- 原理:hash模式监听hashchange事件来实现路由和页面的改变,history使用pushState和replaceState仅仅使得state对象从而改变当前 url 地址,不会触发popState,popState只会在go、forward、back等操作才会触发.
- 表现方式不一样,hash模式有一个hash值,在url中#的后面,可以通过location.hash直接获取到hash值,histroy就是标准的url格式,/xxx/xxx的格式。