路由就是配置url地址和组件的一一对应关系,只要输入地址,就会加载对应的组件
1.路由对象
- $router:路由实例对象,提供了很多跳转方法
addRoutes:动态添加路由(把算出来的路由 重新添加进去)
back:返回
forward:前进
go:去第几个
push//跳转
this.$router.push({path:"/"})
replace//替换地址的路径,1跳2跳3后,this.$router.replace("/")会直接从3到1
- $route:路由信息对象,提供了很多有用的属性
matched:当前匹配到的路由对象,是一个数组(用来实现面包屑)
meta:路由原信息对象(其实就是一个空对象,可以自己在路由中往里面配置自己需要的字段,就可以获取到)
query:获取路由参数 this.$router.push({path:"/",query:{name:"小貂蝉"}}) 获取参数:this.$route.query.name
注意:地址栏带参数,适量少量参数
params:获取路由参数 this.$router.push({name:"xx",params:{age:22}}) 获取参数:this.$route.params.22
注意:params参数,刷新数据会丢失(本地存一份)
2.路由模式
-
浏览器环境
-
hash模式 地址栏带#
- 底层基于
onhashchange
- 底层基于
-
history模式 地址栏不带#
- 底层基于
pushState
- 缺点: 打包上线,如果刷新页面,会报错404, 需要后端配置重定向!!!!
- 依赖 HTML5 History API 和 服务器配置 (必须要后端 配合 才可以)
- 底层基于
-
-
node环境
- abstract 【如果发现没有浏览器的 API,路由会自动强制进入这个模式】
<script>
// 路由的底层代码 就是监听地址栏hash地址的变化,使用 onhashchange, 地址变化的时候,去局部更新dom, 整个浏览器不会刷新。
window.onhashchange = function () {
console.log("hash地址改变...");
};
</script>
// history路由的底层原理是: 使用 history的 pushState 方法,这个方法会改变地址栏的url地址,但是不会刷新浏览器,不会向服务器发送请求,给人的感觉是页面切换了,其实没有刷新,可以通过dom操作,局部更新页面。
btn1.addEventListener("click", function () {
history.pushState({ page: 1 }, "title-1", "page1");
});
btn2.addEventListener("click", function () {
history.pushState({ page: 2 }, "title-2", "page2");
});
3.路由配置
new Router({
routes: [
{path: '', component: 组件},
{path: '', component: () => import('组件路径'),children: [ // 懒加载组件
{path: '', component: 组件},
]}
]
})
4.路由守卫
- 全局前置守卫 (判断用户是否登录 拦截地址栏直接输入地址) 写全局
router.beforeEach((to, from, next) => {
// to: 要去的目标路由对象
// from: 要离开的路由对象
// next: 放行
})
- 全局后置守卫 (写全局)
router.afterEach((to, from) => {
// to: 要去的目标路由对象
// from: 要离开的路由对象
// next: 放行
})
- 路由独享守卫 (写路由配置中)
{
path: "/about",
name: "About", // 命名式路由
component: () => import("../views/About.vue"),
// 路由独享守卫
beforeEnter: (to, from, next) => {
console.log('进入路由之前',to, from, next)
next()
}
}
- 组件内的守卫
beforeRouteEnter(to, from, next) {
},
beforeRouteUpdate(to, from, next) {
},
beforeRouteLeave(to, from, next) {
}
5.前端权限
- 前端权限(让用户无法看到某个元素,并无法通过URL进入):
-
菜单权限(已登录的用户,无法看到非自己权限的菜单按钮)
核心:给菜单数据增加权限数组,计算属性过滤返回新数组
-
防止URL非法访问,路由拦截
核心:路由meta对象中增加权限数组,通过路由生命周期判断权限并进行拦截
router.beforeEach((to,from,next)=>{
if(to.path==="/login"){
next()
}else{
if(to.meta.role.includes(localStorage.role)){
next()
}else{
next("/404")
}
}
})
3.元素权限:控制某些按钮,输入框之类的权限
核心:vue的自定义指令,给要控制的组件绑定自定义指令
//在main.js中
app.directve("指令名称",{
触发的时机(dom,obj){//触发时机例如:mounted
dom:绑定指令的dom节点
obj:.value获取指令传入的值
}
})
<a v-指令名称="要传入的值"></a>
//或者用v-if
- 后端权限(让每个接口有token,token有效&&有权限,接口才会返回数据,否则401)
核心:在请求拦截器中(.interceptors.request.use)戴在每个请求头上config.headers.Authorization = token
6. Vue前端实现权限的思路
1. 登录成功,后端返回角色,存入本地。
2. 把路由一分为二,静态路由和动态路由.在路由meta中配置roles数组,
数组里面包含的角色就可以访问该路由,不配置的默认可以访问.
3. 计算出当前角色有权限访问的路由,通过addRoutes加入路由实例对象中.
4. 通过算出来的路由数组,计算出有权限访问的菜单,动态循环渲染权限菜单.
# 注意踩坑:同一台电脑,切换用户的时候,退出系统,调用 location.reload() 刷新一下页面,
否则上一个用户的权限可能还在。
后端实现方案:
1. 登录成功,后端返回计算好的路由列表
2. 使用addRoutes方法,动态添加路由
3. 动态渲染菜单.