解决无效token问题
这里先说明一下,在黑马这个课程里,我在获取左侧菜单栏的数据的时候就出现了无效token,但是我那个时候认为不重要,就在script标签的data里写死了数据,也是利用循环做出效果的,大伙可以看一下。但是在后面做用户列表获取数据的时候还是不能获取数据,输出无效token
文件截图(注意红色框这里) 首先附上源码
login.vue文件(这个一般没什么问题)
<template>
<div class="login_container">
<div class="login_box">
<!-- 头像区域 -->
<div class="avatar_box">
<img src="../assets/logo.png" alt="">
</div>
<!-- 登录表单区域 -->
<el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" label-width="0px" class="login_form">
<!-- 用户名-->
<el-form-item prop="username">
<el-input v-model="loginForm.username" prefix-icon="el-icon-user"></el-input>
</el-form-item>
<!-- 密码-->
<el-form-item prop="password">
<el-input v-model="loginForm.password" prefix-icon="el-icon-key" type="password"></el-input>
</el-form-item>
<!-- 按钮区域-->
<el-form-item class="btns">
<el-button type="primary" @click="Login">登录</el-button>
<el-button type="info" @click="resetLoginForm">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
export default {
data() {
return {
// 数据绑定对象
loginForm: {
username: 'admin',
password: '123456'
},
// 验证规则对象
loginFormRules: {
//验证用户
username: [
{required: true, message: '请输入用户名', trigger: 'blur'},
{min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur'}
],
password: [
{required: true, message: '请输入登录密码', trigger: 'blur'},
{min: 3, max: 15, message: '长度在 3 到 15 个字符', trigger: 'blur'}
]
}
}
},
methods: {
Login() {
// 预验证
this.$refs.loginFormRef.validate(async valid => {
//未验证通过则直接return
if (!valid) return;
//不加await的化不会打印出数据,await只能用于async修饰的函数
const { data:res } = await this.$http.post("login", this.loginForm);
// {data:res}解构,将得到的返回值的data解构为res
// console.log(res.meta.statusText)
//从res的元数据中得到返回状态
if (res.meta.status !== 200) return this.$message.error("登录失败");
this.$message.success("登录成功");
window.sessionStorage.setItem('token', res.data.token);
this.$router.push("\home");
console.log(res.data.token)
});
},
//重置登录表单
resetLoginForm() {
// console.log(this)
// ui框架自带的form表单方法
this.$refs.loginFormRef.resetFields();
}
}
}
</script>
<!--加上scoped是将样式应用于此组件,不加是全局-->
<style lang="less" scoped>
.login_container {
background-color: rgba(21, 35, 242, 0.25);
height: 100%;
}
.login_box {
width: 450px;
height: 300px;
background-color: white;
border-radius: 3px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
.avatar_box {
height: 130px;
width: 130px;
border: 1px solid #eee;
border-radius: 50%;
padding: 10px;
box-shadow: 0 0 10px #ddd;
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
img {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #eee;
}
}
.login_form {
position: absolute;
bottom: 0;
width: 100%;
padding: 0 20px;
box-sizing: border-box;
}
.btns {
display: flex;
justify-content: flex-end;
}
}
</style>
home.vue文件代码(这个也没有问题)
<template>
<el-container class="home-container">
<el-header>
<div>
<img src="../assets/touxiang.png" alt="" class="header-img" />
<span>电商后台管理系统</span>
</div>
<el-button type="info" @click="logout">退出</el-button>
</el-header>
<el-container>
<el-aside :width="isCollapse ? '64px' : '200px' ">
<div class="toggle-button" @click="toggleCollapse">|||</div>
<!--左侧菜单栏-->
<el-menu
background-color="#333744"
text-color="#fff"
active-text-color="#409EFF"
unique-opened
:collapse="isCollapse"
:collapse-transition="false"
router
:default-active="activePath"
>
<!--一级菜单-->
<el-submenu :index="item.label" v-for="(item, index) in menulist" :key="index">
<template slot="title">
<i :class="'el-icon-' + item.icon"></i>
<span>{{ item.label }}</span>
</template>
<!--二级菜单-->
<el-menu-item-group>
<el-menu-item :index="subItem.path" v-for="(subItem,subIndex) in item.children" :key="subIndex" @click="saveNavState(subItem.path)">
<i :class="'el-icon-' + subItem.icon"></i>
<span>{{subItem.label}}</span>
</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<!--右侧内容主体区域-->
<el-main>
<!--路由占位符-->
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
data() {
return {
//左侧菜单栏数据
menulist: [
{
label: '用户管理',
icon: 'user-solid',
children: [
{
path: '/users',
label: '用户列表',
icon: 'menu'
}
]
},
{
label: '权限管理',
icon: 'box',
children: [
{
path: '/roles',
label: '角色列表',
icon: 'menu'
},
{
path: '/rights',
label: '权限列表',
icon: 'menu'
}
]
},
{
label: '商品管理',
icon: 'shopping-bag-1',
children: [
{
path: '/goods',
label: '商品列表',
icon: 'menu',
},
{
path: '/attributes',
label: '分类参数',
icon: 'menu',
},
{
path: '/categories',
label: '商品分类',
icon: 'menu',
},
]
},
{
label: '订单管理',
icon: 'tickets',
children: [
{
path: '/orders',
label: '订单列表',
icon: 'menu'
}
]
},
{
label: '数据统计',
icon: 'data-line',
children: [
{
path: '/reports',
label: '数据报表',
icon: 'menu'
}
]
}
],
//是否被折叠
isCollapse: false,
//被激活的连接地址
activePath: ''
}
},
created(){
this.getMenuList()
this.activePath = window.sessionStorage.getItem('activePath')
},
methods: {
logout() {
window.sessionStorage.clear()
this.$router.push('/login')
},
//获取所有的菜单
// async getMenuList() {
// const {data: res} = await this.$http.get('/menus')
// if(res.meta.status !== 200) return this.$message.error(res.meta.msg)
// this.menulist = res.data
// console.log(res);
// },
// 获取所有的菜单
async getMenuList() {
const { data: res } = await this.$http.get('/menus')
if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
this.$message.success(res.meta.msg)
res.data.unshift(this.welcome)
this.menuList = res.data
console.log(res, 'menus')
},
//菜单折叠展开
toggleCollapse() {
this.isCollapse = !this.isCollapse
},
//保存连接的激活状态
saveNavState(activePath) {
window.sessionStorage.setItem('activePath', activePath)
this.activePath = activePath
},
},
}
</script>
<style lang="less" scoped>
.home-container {
height: 100%;
}
.header-img {
height: 60px;
}
.el-header {
background-color: #373d41;
display: flex;
justify-content: space-between;
padding-left: 0%;
align-items: center;
color: #fff;
font-size: 20px;
> div {
display: flex;
align-items: center;
span {
margin-left: 15px;
}
}
}
.el-aside {
background-color: #333744;
.el-menu {
border-right: none;
}
}
.el-main {
background-color: #eaedf1;
}
.iconfont {
margin-right: 10px;
}
.toggle-button {
background-color: #4a5064;
font-size: 10px;
line-height: 24px;
color: #fff;
text-align: center;
letter-spacing: 0.2em;
cursor: pointer;
}
</style>
最后!!!
main.js文件(这个有问题)
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import App from './App.vue'
import router from './router'
import './axios/index'
import './components/login.vue'
import './assets/css/globe.css'
Vue.use(ElementUI)
Vue.prototype.$axios = axios
import axios from 'axios'
//import { config } from 'vue/types/umd'
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
axios.interceptors.request.use(config => {
// 登录授权 请求验证是否有token 需要授权的 API ,必须在请求头中使用 `Authorization` 字段提供 `token` 令牌
config.headers.Authorization = window.sessionStorage.getItem('token')
return config // 必须返回否则没有值
})
Vue.prototype.$http = axios;
//axios.defaults.$axios = axios;
Vue.config.productionTip = false
//Vue.prototype.HOST='/api';
// 将vue的原型http对象设置为axios,以后用这个原型就可以直接使用
new Vue({
el: '#app',
router,
render: h =>h(App)
}).$mount("#app")
注意引入的这个import ‘./axios/index’。我去看别人的码云上看别人的代码,删了不重要的再改一下运行后就可以获取菜单的数据了。 最后排查的时候发现,只要把import './axios/index (删了)就可以了。 有没有大佬知道这是问什么呢???欢迎指教啊!!!
|