把token放在vuex

token一定要存在storage缓存中,否则刷新一下,
store会重新被加载,token就没了;

有人问了为什么放在store呢
那存在store是不是多余了,这个也是为了数据统一管理吧,
也是数据可视化,因为缓存中的数据代码中是看不见的

2种情况
  单独token一个独立接口
  登录接口成功里面存token放置在vuex当中

如下述

 单独token一个独立接口

1 手动存储 使用缓存

index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import config from "@/config";
const href21 = `${config.baseUrl22}`;
const store = new Vuex.Store({
	state: {
		token: [],
	},
	getters: {
		getToken(state, getters) {//getter相当于计算属性 获取state的值
			return state.token
		}
	},
	mutations: {// 用于修改 state 里面的数据
		saveToken(state, data) {
			state.token = data
		}
	},
	actions: {//执行 store.commit 是异步的
		askFo({ commit, state }) {
			return new Promise((resolve, reject) => {
				uni.request({//这个请求接口是uni的 如果写你的记得改下
					url: `${href21}?ticket=8a118855753fd59d01756765462c5b9a&type=3`,
					method: "GET",
					success(res) {
						resolve(res.data.data);//这个接口是token (res.data.data的到的是token值)
						localStorage.setItem("token", res.data.data);//得到的token在这里本地存储
						// uni.setStorageSync("token","res")//这是uni默认存储的方法
						commit('saveToken', res)
					},
					fail(err) {//uni自带的错误返回
						reject(err, 1212);
					}
				})
			})
		},
	}
})

export default store

放请求拦截器里/其他页面调取

在页面的生命周期初始化当中
 console.error(localStorage.getItem("token"))

在这里插入图片描述

console.error(this.$store.getters.getToken)//得到getter的值
console.error(this.$store.state.token)//得到state的值

2 调用插件 直接写入插件*

这个插件就相当于把缓存直接写好 直接调取state的值就可以了在其他页面当中

使用插件持有化 安装插件

npm i --save vuex-persistedstate

src/store/index.js中引入该插件

import Vue from 'vue'
import Vuex from 'vuex'
//引入持久化插件
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)
const store = new Vuex.Store({
 //进行配置
	 plugins: [createPersistedState({
		storage: window.sessionStorage, // 默认是 localStorage,这里改成sessionStorage
		key:"store", //存储在sessionStorage里面的key名====自定义
		reducer: (state) => {
		  return {
			// 要存储的数据:用es6扩展运算符的方式存储了state中所有的数据(缓存全部的state)
			...state   
			// 默认是全部缓存,也可以写成下面这种形式,只缓存需要缓存的
			// token: state.token
		  }
		}              
	  })],
	state: {
	},
})

index.js

import Vue from 'vue'
import Vuex from 'vuex'
//引入持久化插件
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)
import config from "@/config";
const href21 = `${config.baseUrl22}`;
const store = new Vuex.Store({
	 //进行配置
	 plugins: [createPersistedState({
		storage: window.sessionStorage, // 默认是 localStorage,这里改成sessionStorage
		key:"store", //存储在sessionStorage里面的key名====自定义
		reducer: (state) => {
		  return {
			// 要存储的数据:用es6扩展运算符的方式存储了state中所有的数据(缓存全部的state)
			...state   
			// 默认是全部缓存,也可以写成下面这种形式,只缓存需要缓存的
			// token: state.token
		  }
		}              
	  })],
	state: {
		token: [],
	},
	getters: {
		getToken(state, getters) {//getter相当于计算属性 获取state的值
			return state.token
		}
	},
	mutations: {// 用于修改 state 里面的数据
		saveToken(state, data) {
			state.token = data
		}
	},
	actions: {//执行 store.commit 是异步的
		askFo({ commit, state }) {
			return new Promise((resolve, reject) => {
				uni.request({//这个请求接口是uni的 如果写你的记得改下
					url: `${href21}?ticket=8a118855753fd59d01756765462c5b9a&type=3`,
					method: "GET",
					success(res) {
						resolve(res.data.data);//这个接口是token (res.data.data的到的是token值)
						commit('saveToken', res)
					},
					fail(err) {//uni自带的错误返回
						reject(err, 1212);
					}
				})
			})
		},
	}
})

export default store

放请求拦截器里/其他页面调取

//直接这样拿取
console.error(this.$store.state.token)

在登录的接口里面的token,登录成功进行获取对应的token,放在vuex里面
  • 封装storage是可选的,不封装就用原生的呗;创建store是必须的!
  • token一定要存在storage缓存中,否则刷新一下,store会重新被加载,token就没了;
  • 那存在store是不是多余了,这个也是为了数据统一管理吧,也是数据可视化,因为缓存中的数据代码中是看不见的~

封装存储storage

封装的存储方法在下方链接
// 存 取 清除 token
    set(key, value) {
        localStorage.setItem(key, JSON.stringify(value));
        // localStorage.key = value;
        // localStorage[key] = value;
    },
    get(key) {
        return JSON.parse(localStorage.getItem(key));
    },
    remove(key) {
        localStorage.removeItem(key);
    },

整体封装方法(—存储在其中—)

创建store

import Vue from 'vue'
import Vuex from 'vuex'
import common from '../utils/common';//这个是引入封装的存储方法
Vue.use(Vuex)
const store = new Vuex.Store({
    state:{
     token:'',
    },
    getters:{
        getToken(state){
            return state.token || common.get("token") || "";
        }
    },
    mutations:{
        // 进行赋值state的变量
        setToken(state ,token){
            state.token = token;
            common.set('token', token);
        },
        // 清空token  登出
        delToken(state) {
            state.token = "";
            common.remove("token");
          },
    },
    actions:{},
    modules:{}
})
export default store

创建request

把对应的token放在请求拦截器
判断如果有token添加到请求头当中
放在响应拦截器里面
判断http状态码为401就是没有权限对应跳转到login页面
import axios from 'axios'
import store from '@/store'
import router from '@/router'
import { MessageBox, Loading, Message } from 'element-ui'
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_URL,
  timeout: 5000
})
let loadingAll;//配置一个loading实例,方便后面使用
let loading_count = 0; //请求计数器
function startLoading() {
  if (loading_count == 0) {
    // 调用其他loading效果在页面引入放在这个块级里面
    loadingAll = Loading.service({
      lock: true,
      text: "别急,请求加载数据中...",
      fullscreen: true,
      background: "rgba(0,0,0,0.7)",
      spinner: 'el-icon-loading',//自定义加载图标类名
    });
  }
  //请求计数器
  loading_count++;
}
function endLoading() {
  loading_count--;//只要进入这个函数,计数器就自减,直到。。
  if (loading_count <= 0) {
    loadingAll.close();
  }
}
// 请求拦截器(放token)
service.interceptors.request.use(
  config => {
    startLoading()//开启loading
    /*
    判断是否需要token,则放在请求头。
     store.getters.getToken;获取的getter值
     Authorization是根据后端自定义字段
    */ 
    config.headers.token = store.getters.getToken;
    return config;
  },
  error => {
    return Promise.reject(error)
  }
)
// 响应拦截器(放提示信息)
service.interceptors.response.use(
  response => {
    endLoading()//关闭loading
    /*
    进行判断是否为200 有则提示正确信息,无提示err信息
    判断是否200根据返回情况而定
    */ 
    if (response.data.meta.status == '200') {
      Message({
        message: response.data.meta.msg,
        type: 'success',
        duration: 5 * 1000
      })
    } else {
      Message({
        message: response.data.meta.msg,
        type: 'error',
        duration: 5 * 1000
      })
    }
    return response.data
  },
  error => {
    endLoading()//关闭loading
    //判断错误信息进行提示
    if (error && error.response) {
      // 1.公共错误处理
      // 2.根据响应码具体处理
      switch (error.response.status) {
        case 400:
          error.message = '错误请求'
          break;
        case 401:
          //可能是token过期,清除它
          store.commit("delToken");
          router.replace({ //跳转到登录页面
              path: '/',
               // 将跳转的路由path作为参数,登录成功后跳转到该路由
              // query: { redirect: router.currentRoute.fullPath }
          });
          error.message = '未授权,请重新登录'
          break;
        case 403:
          error.message = '拒绝访问'
          break;
        case 404:
          error.message = '请求错误,未找到该资源'
          window.location.href = "/NotFound"
          break;
        case 405:
          error.message = '请求方法未允许'
          break;
        case 408:
          error.message = '请求超时'
          break;
        case 500:
          error.message = '服务器端出错'
          break;
        case 501:
          error.message = '网络未实现'
          break;
        case 502:
          error.message = '网络错误'
          break;
        case 503:
          error.message = '服务不可用'
          break;
        case 504:
          error.message = '网络超时'
          break;
        case 505:
          error.message = 'http版本不支持该请求'
          break;
        default:
          error.message = `连接错误${error.response.status}`
      }
    } else {
      // 超时处理
      if (JSON.stringify(error).includes('timeout')) {
        Message.error('服务器响应超时,请刷新当前页')
      }
    }
    Message.error(error.message)
    return Promise.reject(error.response.data)
  }
)
export default service

路由router,并设置路由守卫

import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '@/store'//引入store必填
import common from '@/utils/common';//引入存储方法必填
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
  // 这个不是放home路径home路径单独引入进来
  {
    path: '/',
    name: 'Home',
    redirect: '/login',
    // 某些页面规定必须登录后才能查看 ,可以在router中配置meta,将需要登录的requireAuth设为true,
  },
  { path: '/login', name: 'login', component: () => import('@/views/login/index.vue') },
  // 命名不能用特殊字符
  { path: '/home', component: Home },//这个是跳转home的页面主页面
  // // 404
  // { path: '/404', name: '404', component: () => import('@/views/errPage/404.vue') }
]
const router = new VueRouter({ routes })
// 首先拿到token 
if (common.get("token")) {
  store.commit("setToken", common.get("token"));
}
// 其次判断是否包含token 必填
router.beforeEach((to, from, next) => {
//判断是否在登录页 是返回
//判断是否不在登录页是否带token不是或者不带token返回登录页
//否则返回放行
if(to.path==='/login') return next();
 const tokenStr=store.state.token;
 if(!tokenStr){
 return next('/login')
 }else{
   next()
 }
})

export default router

页面当中用

登录页面调取接口对应的token拿取到
<template>
  <div class="main">
    <div class="sec">
      <el-form ref="ruleForm" :rules="loginRules" :model="formRef">
        <h3>系统登录</h3>
        <el-form-item prop="username">
          <el-input
            ref="username"
            prefix-icon="el-icon-user-solid"
            v-model="formRef.username"
            placeholder="请输入账号"
          >
          </el-input>
        </el-form-item>
        <el-form-item prop="password">
          <el-input
            ref="password"
            :type="passwordType"
            prefix-icon="el-icon-s-tools"
            v-model="formRef.password"
            show-password
            placeholder="请输入密码"
          >
          </el-input>
        </el-form-item>
        <SliderCheck
          style="margin: 30px 0"
          :successFun="handleSuccessFun"
          :errorFun="handleErrorFun"
        ></SliderCheck>
        <el-form-item>
          <el-button
            type="primary"
            v-if="isDisabled"
            disabled
            style="width: 100%"
            >登录</el-button
          >
          <el-button
            type="primary"
            v-else
            @click="onSubmit('ruleForm')"
            style="width: 100%"
            >登录</el-button
          >
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>
<script>
import SliderCheck from "./components/sliderCheck.vue";
import * as math from "@/api/api";
import store from "@/store/index";
export default {
  data() {
    const validatePassword = (rule, value, callback) => {
      if (value.length < 6) {
        callback(new Error("密码最少6位"));
      } else {
        callback();
      }
    };
    return {
      formRef: {
        username: "admin",
        password: "123456",
      },
      passwordType: "password",
      iseye: true,
      isDisabled: true,
      loginRules: {
        username: [
          { required: true, message: "请输入用户名称", trigger: "blur" },
        ],
        password: [
          { required: true, trigger: "blur", validator: validatePassword },
        ],
      },
    };
  },
  components: { SliderCheck },
  methods: {
    // 滑块验证成功回调
    handleSuccessFun() {
      this.isDisabled = false;
    },
    // 滑块验证失败回调
    handleErrorFun() {
      this.isDisabled == true;
    },
    onSubmit(loginForm) {
      //对应于ref的值要一致
      this.$refs[loginForm].validate((valid) => {
        if (!valid) return; //不符合返回
        let params = {
          username: this.formRef.username,
          password: this.formRef.password,
        };
        math.getLogin(params).then((res) => {
          // 判断username是否有值 有则返回成功进行跳转
          if (res.meta.status == '200') {
            this.$router.push({
             path: "/home", //这个是跳转的页面
              query: {
                useIndex:res.data,
              },
            });
          }
          /*2种1 把请求成功的token存储在vuex中(*)2 把请求成功的token存在sessionStorage*/
          this.$store.commit("setToken", res.data.token);//调取getter里面的方法.
        });
      });
    },
  },
};
</script>
<style lang="scss" scoped>
</style>

在这里插入图片描述

项目参考直达车

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值