目录
路由守卫
-
作用:监听路由的变化
- 关于更新你点击的页面,显示对应的标题!
- 这就需要在监听路由的跳转,实时的显示对应的标题!
-
官网:
https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB
- to => 去往那个路由
- 由于to去往的路由,可能存在路由的嵌套,那么最好的话,使用
to.matched[0] 取出第一个路由
- 由于to去往的路由,可能存在路由的嵌套,那么最好的话,使用
- from => 从那个路由跳转
- next() => 就是一个管道运输,执行下一个的钩子函数,如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
- to => 去往那个路由
-
全局守卫
- 全局前置路由守卫 => router.beforeEach(function(to,from,next){})
- 全局后置路由守卫 => router.afterEach(function(to,from){})
- 注意点:这个全局路由守卫是,配置在router/index.js 路由文件下的
- 常常用于配置用户权限 还有 当前活跃路由的title
//配置 当前活跃的路由的 title
router.beforeEach((to, from, next) => {
document.title = to.meta.title
next();
})
-
组件内的守卫
-
beforeRouteEnter(to, from, next) {}
- 进入当前路由执行前,组件实例还没被创建
-
beforeRouteUpdate(to, from, next) {} (2.2 新增)
- 在当前路由改变,但是该组件被复用时调用
- 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
- 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
- 可以访问组件实例
this
- 在当前路由改变,但是该组件被复用时调用
-
beforeRouteLeave(to, from, next) {}
- 导航离开该组件的对应路由时调用
- 可以访问组件实例
this
-
注意点:组件内使用时配置这个路由守卫即可!
methods:{ }, beforeRouteEnter(to, from, next) { console.log("我是Edit组件,进入组件前", to); next(); }, beforeRouteUpdate(to, from, next) { console.log("我是Edit组件,路由更新,复用组件", to); next(); }, beforeRouteLeave(to, from, next) { console.log("我是Edit组件,离开当前组件,去往", to); next(); },
-
-
路由独享的守卫
- 你可以在路由配置上直接定义 beforeEnter 守卫:
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { next() } } ] })
路由的执行步骤
- 导航被触发。
- 在失活的组件里调用beforeRouteLeave离开守卫。
- 所谓失活组件,就是从当前组件离开,去往下一个组件,这个当前组件就是失活组件
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
- 就是两个路由路径一致的时候,就参数不一致,那么两者切换的时候,会复用前一个组件的内容!
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 所谓激活组件,就是从上一个组件离开,来到当前组件,这个当前组件就是激活组件
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
路由守卫相关权限操作
点击当前组件,显示对应title
- 01:需要在路由配置的时候,设置一个meta对象,里面有着title属性 => 这是关于需要显示的title
- 02:需要使用路由守卫, => 取出从哪里跳转到哪里路由的title属性
router/index.js
//路由守卫
router.beforeEach((to, from, next) => {
document.title = to.matched[0].meta.title
<!-- document.title = to.meta.title -->
next();
})
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [{
path: '/',
name: 'Home',
meta: {
title: "首页"
},
component: Home
}, {
path: '/profile/:id/:name',
name: 'Profile',
meta: {
title: "档案"
},
component: () => import('../views/Profile.vue')
}, {
path: '/news',
name: 'News',
meta: {
title: "新闻"
},
component: () => import('../views/News.vue')
}
]
const router = new VueRouter({
// mode: 'history',
// base: process.env.BASE_URL,
routes
})
//路由守卫
router.beforeEach((to, from, next) => {
document.title = to.matched[0].meta.title
next();
})
export default router
使用路由守卫的方式实现登录跳转判断!
- 需求:
- 当你点击列表之中的 用户列表 但是你没有登录 那么像跳转到登录组件
- 当你登录完成后,那么再重新跳转回到 用户列表 组件!
router/index.js路由的配置
-
对于每一个路由都需要设置 授权管理 使用 meta:{} => meta字段(元数据) => 里面可以书写 title requireAuth 等!
{ path: "/user", meta: { title: "用户", requiresAuth: true //关于用户 这个path 都需要权限 才能访问 这个权限就是token }, component: () => import("../pages/user/Default.vue"), children: [{ path: "/", redirect: "list" }, { path: "list", name: "UserList", meta: { title: "用户列表" }, component: () => import("../pages/user/List.vue") }, { path: "add", name: "UserDdd", meta: { title: "用户添加" }, component: () => import("../pages/user/Edit.vue") }, { name: "UserEdit", path: "edit/:id", meta: { title: "用户编辑" }, component: () => import("../pages/user/Edit.vue") } ] },
-
在全局前置路由守卫 之中 判断当前路由是否登录了,才可访问! 判断是否授权 => requiresAuth
to.matched.some(item =>item.meta.requireAuth)
//判断目标路由是否需要登录 才可访问!
//当匹配的路由 项之中 有这个授权请求 那么就先从本地拿一下 本地的存储用户信息!
router.beforeEach(function (to, from, next) { //判断当前路由是否需要登录授权!,才能访问 if (to.matched.some(item => item.meta.requiresAuth)) { //从本地拿到 存储的userInfo信息! 用户信息 let userInfo = localStorage.getItem('userInfo') || {}; try { userInfo = JSON.parse(userInfo) } catch (err) { userInfo = {} } // 判断当前用户信息是否包含token if (userInfo.authorization) { //发起请求 验证token是否过期 暂时先next() $request.get("/jwtverify", { // 发起请求 检验token是否过期 params: { authorization: userInfo.authorization } }) .then(res => { // console.log("我是data啊", res.data.code) if (res.data.code === 1) { next() } else { next({ path: "/login", query: { redirectTo: to.fullPath } }) } }) next(); } else { //若不存在 token 那么就去往 登录页面! next({ path: "/login", query: { // 跳转到登录页面,并传递 当前点击想要去的 目标页面路径 redirectTo: to.fullPath } }) } } else { next(); } })
LoginOut.vue组件 之登录按钮
- 这边包含验证码! 注意点:就是svg验证码 是一个 html标签 那么定义一个变量vcodeSvg 来接受,然后使用v-html=“vcodeSvg”
//点击 验证码 发起请求 由于最开始需要验证码 需要在created(){} 之中 先调用一下这个方法! async getVcode() { const res = await this.$request.get("/vcode"); this.vcodeSvg = res.data.data; },
- 点击登录:
- 先验证过了,然后在发起请求!
const res = await this.$request.get("mlogin",{ params:{ ...this.ruleFrom //拿到表单的值 发起请求 } })
- 发起请求后,返回数据,判断是否成功,成功的话 那么先把返回来的用户信息存入本地之中
localStorage.setItem("userInfo", JSON.stringify(res.data.data));
- 点击登录后,需要返回原本用户 想要去对应path
//this.$route.query 这是路由配置之中 设置的返回的那个想要去的目标path 参数! 重定向To 默认为home const { redirectTo = "/home" } = this.$route.query this.$router.replace(redirectTo);
- 先验证过了,然后在发起请求!
<div class="login-wrap">
<el-form
:label-position="labelPosition"
label-width="80px"
class="login-form"
:model="ruleForm"
>
<h2>用户登录</h2>
<el-form-item label="用户名">
<el-input v-model="ruleForm.username"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="ruleForm.password"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="vcode">
<!-- prop属性设置需要校验的字段名 -->
<el-input v-model="ruleForm.vcode">
<template v-slot:append>
<div v-html="vcodeSvg" class="vcode" @click="getVcode"></div>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-checkbox label="下次免登陆" v-model="ruleForm.mdl"></el-checkbox>
</el-form-item>
<el-button type="primary" class="login-btn" @click.prevent="handleLogin">登录</el-button>
</el-form>
</div>
data() {
return {
labelPosition: "left",
vcodeSvg: "", //用于存放 请求回来的svg验证码这个html标签
ruleForm: {
username: "",
password: "",
vcode: "",
mdl: true,
},
};
},
created() {
//一开始 发起请求 拿到验证码!
this.getVcode();
},
methods: {
async handleLogin() {
// 一进入登录界面的时候,就发起请求 请求验证码!
const res = await this.$request.get("/mlogin", {
params: {
...this.ruleForm,
},
});
// console.log("我是点击登录", res.data.data);
if (res.data.code === 1) {
this.$message.success("登录成功");
localStorage.setItem("userInfo", JSON.stringify(res.data.data));
//路由守卫 设置了 最开始 点击那里 就返回那个的path
const { redirectTo = "/home" } = this.$route.query;
this.$router.replace(redirectTo);
}
},
async getVcode() {
const res = await this.$request.get("/vcode");
this.vcodeSvg = res.data.data;
},
},