若依Vue2.0框架学习之路由跳转
1.若依Vue2.0框架学习之按钮权限(hasPersi)
2.若依Vue2.0框架学习之路由跳转
免责声明
- 新项目在若依前后端分离(Vue2.6.x + Springboot2.2.x)模板基础上进行项目开发,苯人真得学学模板吧!理解错误概不负责,毕竟ko no 菜鸡一枚 da。
- 我们幼儿园有适合自己看的注释拉满文档!
- 本篇只涉及路由跳转,什么登录流程和权限管理先往后稍稍。
0. next()
前情提要:假设当前导航是从 A 到 B,新的导航是从 A 到 C。
0.1 next()
放行,允许从 A 到 B。
0.2 next(false)
不仅中断当前导航,也没有新的导航。
0.3 next('/xxx') 或 next({ path:'/xxx',... })
中断当前导航,执行新的导航;即又会进入一次前置守卫。
0.4 next(error) 2.4.0+
如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。(船新的api)
1. Vue.config.js 项目启动
const port = process.env.port || process.env.npm_config_port || 80 // 端口 // 省略版 module.exports = { // ... devServer: { host: '0.0.0.0', port: port, // ... } }
项目启动 http://localhost:80/
2. 路由跳转
2.1 router/index.js 路由配置
关注根路径的重定向
// ==== 省略版 ==== import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) /* Layout */ import Layout from '@/layout' // 公共路由 export const constantRoutes = [ { path: '/redirect', component: Layout, hidden: true, children: [ { path: '/redirect/:path(.*)', component: () => import('@/views/redirect') } ] }, { path: '/login', component: () => import('@/views/login'), hidden: true }, { path: '/404', component: () => import('@/views/error/404'), hidden: true }, // ''也可以匹配上'/'的 { path: '', component: Layout, // 重定向到子路由 redirect: 'index', children: [ { path: 'index', component: () => import('@/views/index'), name: 'Index', meta: { title: '首页', icon: 'dashboard', affix: true } } ] }, ] export default new Router({ mode: 'history', // 去掉url中的# routes: constantRoutes })
2.2 路由前置守卫
2.2.1 未登录(cookie 中无 token),直接访问非白名单内某配置了的页面,会跳转到 login 页
permission.js
关注 1. 跳转到了login页 2. fullPath为 /login?redirect=/xxx
import router from './router' import store from './store' import { Message } from 'element-ui' import NProgress from 'nprogress' import 'nprogress/nprogress.css' import { getToken } from '@/utils/auth' import { isRelogin } from '@/utils/request' NProgress.configure({ showSpinner: false }) // 只关心路由前置守卫以及路由跳转捏 const whiteList = ['/login', '/register'] // 0. 项目启动 http://localhost:80/ 在router.js 中配置了,重定向到子路由 index,导航是从 / 到 /index router.beforeEach((to, from, next) => { NProgress.start() if (getToken()) { // 略 } else { // a 1. 没有token 3. 没有token if (whiteList.indexOf(to.path) !== -1) { // a 4. to.path == /login 在白名单 // a 5. next() 跳转到 login 页,fullPath 为 /login?redirect=/index 至此 finished next() } else { // 2. 此时 to 路由对象的 path 是 /index 不在白名单 next(`/login?redirect=${to.fullPath}`) // 否则全部跳转到登录页,且此处参数redirect是为了后面点击登录验证成功后直接跳转到本来想访问的页面 // 新的 to 路由对象的 fullPath 为 /login?redirect=/index NProgress.done() } } }) router.afterEach(() => { NProgress.done() })
2.2.2 接上续,点击登录通过验证,跳转到原目标页,这里以 index 举例
views/login.vue
<script> name: "Login", data() { return { // ... redirect: undefined }; }, watch: { // 经过重定向 + 守卫,此时的 $route: { path:"/login",query: {redirect: "/index"},fullpath: "/login?redirect=%2Findex",...} $route: { handler: function(route) { this.redirect = route.query && route.query.redirect; }, immediate: true } }, handleLogin() { this.$refs.loginForm.validate(valid => { if (valid) { // ... this.$store.dispatch("Login", this.loginForm).then(() => { // 暂时只关注这一行,点击登录按钮,验证成功后,跳转到 index.vue to : { path : /index } this.$router.push({ path: this.redirect || "/" }).catch(()=>{}); }).catch(() => { this.loading = false; if (this.captchaEnabled) { this.getCode(); } }); } }); } </script>
permission.js
import router from './router' import store from './store' import { Message } from 'element-ui' import NProgress from 'nprogress' import 'nprogress/nprogress.css' import { getToken } from '@/utils/auth' import { isRelogin } from '@/utils/request' NProgress.configure({ showSpinner: false }) // 只关心路由前置守卫捏 const whiteList = ['/login', '/register'] // 0. 接上文,此时 to : {path : /index} router.beforeEach((to, from, next) => { NProgress.start() if (getToken()) { // b 1. 有token 4. 有token to.meta.title && store.dispatch('settings/setTitle', to.meta.title) if (to.path === '/login') { next({ path: '/' }) NProgress.done() } else { // 判断当前用户是否已拉取完 user_info 信息(因为即使没有也会赋一个默认的,所以只要是 0 肯定没拉) // b 2. 没拉取完,先发送请求获取(这里涉及 vuex 和权限,不展开) if (store.getters.roles.length === 0) { isRelogin.show = true store.dispatch('GetInfo').then(() => { isRelogin.show = false store.dispatch('GenerateRoutes').then(accessRoutes => { router.addRoutes(accessRoutes) // b 3. fulfilled // 此时新的路由为 { path: '/index',replace :true} 这里的 replace属性使得当前的push方法变成像this.$router.replace一样 不会向 history 添加新纪录 next({ ...to, replace: true }) }) }).catch(err => { // rejected store.dispatch('LogOut').then(() => { Message.error(err) // 登出后,此时 cookie 里的 token 已清除;因此同2.2.1 // 但是这里为什么不直接写 next({ path: '/login' }) ??? next({ path: '/' }) }) }) // b 5. 拉取完,直接放行 { path: '/index',replace :true } 跳转到原目标页 } else { next() } } } else { if (whiteList.indexOf(to.path) !== -1) { next() } else { next(`/login?redirect=${to.fullPath}`) NProgress.done() } } }) router.afterEach(() => { NProgress.done() })
2.2.3 已登录(cookie 中有 token),再访问 login 页,会重定向到 index 页
import router from './router' import store from './store' import { Message } from 'element-ui' import NProgress from 'nprogress' import 'nprogress/nprogress.css' import { getToken } from '@/utils/auth' import { isRelogin } from '@/utils/request' NProgress.configure({ showSpinner: false }) const whiteList = ['/login', '/register'] router.beforeEach((to, from, next) => { NProgress.start() if (getToken()) { // c 有 token 再访问 login 页 1. has token 3. has token 6. has token to.meta.title && store.dispatch('settings/setTitle', to.meta.title) if (to.path === '/login') { // c 2. 访问 login 页 匹配上''会重定向,直接改变了to,因此5.的path是 /index next({ path: '/' }) NProgress.done() } else { // 判断当前用户是否已拉取完 user_info 信息(因为即使没有也会赋一个默认的,所以只要是0肯定没拉,好吧这里也涉及权限,暂时不用管) // c 4. 因为直接改变url模拟 肯定会刷新页面,因此走没拉取完 // 注: user_info 存在 vuex 里,vue本质是单页面, 路由的跳转不会刷新页面,但重新输入url会 if (store.getters.roles.length === 0) { isRelogin.show = true store.dispatch('GetInfo').then(() => { isRelogin.show = false store.dispatch('GenerateRoutes').then(accessRoutes => { router.addRoutes(accessRoutes) // c 5. to: { path: '/index' } next({ ...to, replace: true }) }) }).catch(err => { store.dispatch('LogOut').then(() => { Message.error(err) next({ path: '/' }) }) }) } else { // 7. 拉取完了 { path: '/index', replace: true } 放行 next() } } } else { if (whiteList.indexOf(to.path) !== -1) { next() } else { next(`/login?redirect=${to.fullPath}`) NProgress.done() } } }) router.afterEach(() => { NProgress.done() })
本文作者:雨宮莲
本文链接:https://www.cnblogs.com/pupyy/p/17665540.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)