1. 前情
本人Vue菜鸟选手
在本人进行Vue项目时,某天睡醒正坐,突然想到自己的前端项目虽然进行了拦截,但仅限于不同页面的情况下,同页面情况下由于认证解决问题,必定可以在用户A登录后通过管理员相关链接直接访问进入管理员页面进行操作。
于是乎在多方查找解决方法,但不知道为何找不到相关的文章,终于翻了很多篇文章推荐后找到了下面的文章,并进行操作,成功解决了问题。
本文章主要用以个人记录以及分享,且帮助避开上文中存在几次问题。
使用的结构分层与参考链接有些区别,写的有些粗糙,但解决了我的问题,希望大佬轻喷。
2. 我的写法
- 文档结构如下
- router- index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
//举例几个管理员页面
import Administration from '../components/administration.vue'
import QueryCargo from '../components/administration_children/queryCargo.vue'
import Welcome from '../components/administration_children/welcome.vue'
//举例几个用户页面
import User from '../components/visit/user.vue'
import UserWelcome from '../components/visit/userWelcome.vue'
import QueryCargoFD from '../components/visit/queryCargoForV.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/administration',
component: Administration,
//输入administration自动映射到welcome页面
redirect: '/welcome',
//设置为子路由
children: [
{
path: '/welcome',
component: Welcome,
meta: {
// 元数据 requireAuth来做是否需要拦截的判断
requireAuth: true
}
},
{
path: '/queryCargo',
component: QueryCargo,
meta: {
// 元数据 requireAuth来做是否需要拦截的判断
requireAuth: true
}
},
],
},
{
path: '/user',
component: User,
redirect: '/userWelcome',
children: [
{
path: '/userWelcome',
component: UserWelcome,
meta: {
// 元数据 requireAuth来做是否需要拦截的判断
requireAuth: true
}
},
{
path: '/queryCargofd',
component: QueryCargoFD,
meta: {
// 元数据 requireAuth来做是否需要拦截的判断
requireAuth: true
}
},
],
}
]
const router = new VueRouter({
routes
})
export default router
- store- index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
//用到了 sessionStorage,使用sessionStorage ,
//关掉浏览器的时候会被清除掉,和 localStorage 相比,
//比较利于保证实时性。
//我个人使用自己传入sessionStorage中的user的内容来区分用户和管理员
token: sessionStorage.getItem("token"),
user: JSON.parse(sessionStorage.getItem("user")),
//
//允许访问的页面
menuListStatus: [],
//
menuListAd: [],
//
},
mutations: {
//(用户可以访问的页面)
saveMenuListStatus (state,data) {
state.menuListStatus = data;
},
saveMenuListAd (state,data) {
state.menuListAd= data;
},
// set
SET_TOKENN: (state, token) => {
state.token = token
sessionStorage.setItem("token", token)
},
SET_USER: (state, user) => {
state.user = user
sessionStorage.setItem("user", JSON.stringify(user))
},
REMOVE_INFO : (state) => {
state.token = ''
state.user = {}
sessionStorage.setItem("token", '')
sessionStorage.setItem("user", JSON.stringify(''))
}
},
getters: {
},
actions: {
},
modules: {
}
})
- main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from '@/store'
import './plugins/element.js'
//导入全局样式表
import './assets/css/global.css'
import { Message } from "element-ui"
import axios from 'axios'
import _ from 'lodash'
Vue.config.productionTip = false
//配置请求的根路径
//设置反向代理,前端请求默认发送到http://127.0.0.1:8081
axios.defaults.baseURL = 'http://127.0.0.1:8081';
var menuList = [
{
id: 1,
title: '/user'
},
{
id: 2,
title: '/userWelcome'
},
{
id: 3,
title: '/queryCargofd'
},
]
var menuListad = [
{
id: 1,
title: '/administration'
},
{
id: 2,
title: '/welcome'
},
{
id: 3,
title: '/queryCargo'
},
]
// 把拿到的菜单存储在vuex中
store.commit('saveMenuListStatus', menuList);
store.commit('saveMenuListAd', menuListad);
//禁止用户跳管理员及管理员跳用户
//to为去向那个页面,from为从哪个页面来,next为放行
router.beforeEach((to, from, next) => {
//判断是否需要拦截
if (to.meta.requireAuth) {
//进行登陆拦截判断,只有先登录才可以访问,登录后添加token至sessionStorage
if (store.state.token) {
//通过登录后传入sessionStorage的user值判断登录人,admin为管理员
//管理员不可以登录后跳转用户的页面
if (store.state.user.uid === "admin") {
//获取管理员可以访问的页面数组
//这里有些问题,我放在之后的总结讲,标号 1
let menuListAd = store.state.menuListAd;
if (menuListAd && menuListAd.length != 0) {
//对to页面进行对比
let isMenu = deepQuery(menuListAd, to.path);
if (isMenu) {// 若存在,继续访问
next();
}else{
Message({
message: '无权限访问',
type: "warning"
});
next(from.path);
}
} else{
next();
}
}else{
//登陆的是用户,不论具体是谁
//获取用户可以访问的页面数组
let menuListStatus = store.state.menuListStatus; //接口返回可以访问的菜单,存储在vuex中
if (menuListStatus && menuListStatus.length != 0) {
//对to页面进行对比
let isMenu = deepQuery(menuListStatus, to.path);
if (isMenu) {// 若存在,继续访问
next();
} else {
Message({
message: '无权限访问',
type: "warning"
});
next(from.path);
}
} else {
next();
}
}
}else{
//没有登录的情况
next({
path: 'login',
query: { redirect: to.fullPath }
})
}
}else {
next();
}
})
// 查找菜单数组中path是否存在
function deepQuery(tree, path) {
var isGet = false;
var retNode = null;
function deepSearch(tree, path) {
for (var i = 0; i < tree.length; i++) {
console.log(tree[i].children)
console.log(tree[i].length)
console.log(tree[i].id)
console.log(tree[i].title)
if (tree[i].children && tree[i].children.length > 0) {
deepSearch(tree[i].children, path);
}
if (path === tree[i].title || isGet) {
isGet || (retNode = tree[i]);
isGet = true;
break;
}
}
}
deepSearch(tree, path);
return retNode;
}
//配置请求的默认头部
Vue.prototype.$http = axios;
var vueThis = new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
export default vueThis;
3. 自己的代码的问题
- 大部分处理代码堆积在main.js中,但实际上我因为对Vue不熟悉,这是我第一次接触Vue框架(纯纯小白),写法不够优雅,本想要跟参考文章一样将存储数组的代码放在别的地方,但不知道怎么处理,于是干脆写在了main里面,但实际运行起来,每次跳转页面时可能都会跑一趟,挺浪费时间。
在这个地方其实可以之前使用前面的数组名,直接引用里面的内容,交给优秀的你进行改善了。
谢谢你看完,希望能够对你产生帮助。