vue 基于vuex 请求令牌token 刷新令牌token验证

store.js

import Vue from "vue"
import Vuex from "vuex"

/**
    Vuex持久化存储之vuex-persist
    Vuex 解决了多视图之间的数据共享问题。但是运用过程中又带来了一个新的问题是,
    Vuex 的状态存储并不能持久化。也就是说当你存储在 Vuex 中的 store 里的数据,
    只要一刷新页面,数据就丢失了。
    引入vuex-persist 插件,它就是为 Vuex 持久化存储而生的一个插件。
    不需要你手动存取 storage ,而是直接将状态保存至 cookie 或者 localStorage 中
 */
import VuexPersistence from "vuex-persist"

Vue.use(Vuex)

const vuexLocal = new VuexPersistence({
  storage: window.localStorage,
})

/**
 * State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。
 * 
 * 只能通过 mutations 变更 Store 数据,不可以直接操作 Store 中的数据。
 * 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。
 * 
 * actions 用于处理异步任务。
 * 如果通过异步操作变更数据,必须通过 actions,而不能使用 mutations,但是在 actions 中还是要通过触发
 * mutations 的方式间接变更数据。
 * 
 * getters 用于对 Store 中的数据进行加工处理形成新的数据。
 */

export default new Vuex.Store({
    state: {
        access_token: "",
        refresh_token: "",
    },
    mutations: {
        setAccessToken(state, param) {
            state.access_token = param
        },
        setRefreshToken(state, param) {
            state.refresh_token = param
        },
        removeAccessToken(state) {
            state.access_token = ''
        },
        removeRefreshToken(state) {
            state.refresh_token = ''
        },
    },
    actions: {
        setAccessToken(context, param) {
            context.commit('setAccessToken', param)
        },
        setRefreshToken(context, param) {
            context.commit('setRefreshToken', param)
        },
        removeAccessToken(context) {
            context.commit('removeAccessToken')
        },
        removeRefreshToken(context) {
            context.commit('removeRefreshToken')
        }
    },
    getters: {
        getAccessToken(state) {
            return state.access_token
        },
        getRefreshToken(state) {
            return state.refresh_token
        }
    },
    plugins: [vuexLocal.plugin]
})
/*******************************************************************/

request.js

import axios from 'axios'
import store from '@/store'

import {
    Toast
} from 'vant';
import router from '@/router/index';

export function request(config) {
    // 1.创建axios的实例
    const instance = axios.create({
        baseURL: 'http://*********.com',
        timeout: 5000
    })

    // 2.axios的拦截器
    // 2.1.请求拦截的作用
    instance.interceptors.request.use(config => {

        // 获取token
        //const token = store.getters.getToken
        //token && (config.headers.Authorization = token)
        return config
    }, err => {
        return Promise.reject(err);
    })

    // 2.2.响应拦截
    instance.interceptors.response.use(res => {
        if (res.data.code == 100101) {
            Toast.success({
                message: res.data.msg,
                duration: 1.5 * 1000
            })
            store.dispatch('removeAccessToken')
            store.dispatch('removeRefreshToken')
            setTimeout(() => {
                router.replace('/login')
            }, 1500)
        } else if (res.data.code == 100102 || res.data.code == 100103) {
            store.dispatch('removeAccessToken')
            store.dispatch('removeRefreshToken')
            setTimeout(() => {
                router.replace('/login')
            }, 1500)
        } else if (res.data.code == 100000) {
            //处理正确结果
            if (res.data.usertoken.length != 0) {
                store.dispatch('setAccessToken',res.data.usertoken.access_token)
                store.dispatch('setRefreshToken',res.data.usertoken.refresh_token)
            }
            return res.data
        } else {
            return res.data
        }
    }, err => {
        Toast.fail({
            message: err.message,
            duration: 1.5 * 1000
        })
        return Promise.reject(err)
    })

    // 3.发送真正的网络请求
    return instance(config)
}
/*********************************************************************************/

Login.vue

<template>
    <div class="wm-login">
        <div class="SignFlowHeader">
            <h1></h1>
            <p></p>
        </div>
        
        <div class="wm-form">
            <van-form @submit="onSubmit">
              <van-field
                v-model="username"
                name="username"
                label="用户名"
                placeholder="用户名"
                :rules="[{ required: true, message: '请填写用户名' }]"
                    class="yonghuming"
              />
              <van-field
                v-model="password"
                type="password"
                name="password"
                label="密码"
                placeholder="密码"
                :rules="[{ required: true, message: '请填写密码' }]"
              />
              <div style="margin: 40px;">
                <van-button round block type="info" native-type="submit">
                  登录
                </van-button>
              </div>
            </van-form>
        </div>
    </div>
</template>

<script>
    import Vue from 'vue'
    import {login} from '@/model/login.js'
    import { mapActions } from 'vuex'
    import { Toast } from 'vant';
    Vue.use(Toast);
    
    //import axios from 'axios'
    export default {
        name:'Login',
        data() {
            return {
                username:'',
                password:''
            }
        },
        methods: {
            //将指定的 actions 函数,映射为当前组件的 methods 函数
            ...mapActions(['setAccessToken', 'setRefreshToken']),
            
            onSubmit(values) {
                //会员登录
                login(this.username,this.password).then(res=>{
                    if(res.code == 100000){
                        this.setAccessToken(res.usertoken.access_token)
                        this.setRefreshToken(res.usertoken.refresh_token)
                        Toast.success({
                            message: res.msg,
                            duration: 1.5 * 1000
                        })
                        setTimeout(()=>{
                            this.$router.replace('/')
                        },1500)
                    }else{
                        Toast.fail({
                            message: res.msg,
                            duration: 1.5 * 1000
                        })
                    }
                })
            },
        },
    }
</script>

<style scoped="scoped">
    .wm-login .SignFlowHeader{
        padding-top: 10px;
        text-align: center;
        margin-top: 0px;
        height: 108px;
        color: #fff;
        background: #1989fa;
    }
    .wm-login .SignFlowHeader h1 {
        font-size: 30px;
        margin-bottom: 10px;
    }
    .wm-login .SignFlowHeader p {
        font-size: 16px;
    }
    
    .wm-form {
        margin-top: 60px;
    }
    .van-field {
        font-size: 20px;
    }
    .yonghuming {
        margin-bottom: 30px;
    }
</style>

/********************************************************************************/

<template>
    <div class="home">
        <van-sticky>
            <van-nav-bar style="background-color: #FF5777;">
                <template #title>
                    <span style="color: #FFFFFF;">首页</span>
                </template>
            </van-nav-bar>
        </van-sticky>

        <div class="wm-baodao">
            <p>列表</p>
            <van-cell title="查看" size='large' is-link to="/student" />
        </div>

        <div class="wm-baodao">
            <p>流程</p>
            <van-cell :title="report.snb_name" size='large' value="需缴费" is-link @click="gotodetail(report.snb_id)" />
        </div>

    </div>
</template>

<script>
    // @ is an alias to /src
    import Vue from 'vue';
    import {
        Toast
    } from 'vant';
    Vue.use(Toast);

    import {
        get_report
    } from '@/model/home.js'

    export default {
        name: 'Home',
        data() {
            return {
                report:{}
            }
        },
        components: {},
        created() {
            //获取
            get_report().then(res => {
                if(res.code == 100000){
                    this.report = res.result
                }else{
                    Toast.fail({
                        message: res.msg,
                        duration: 1.5 * 1000
                    })
                }
            });
        },
        methods: {
            //将指定的 actions 函数,映射为当前组件的 methods 函数
            //跳转详情
            gotodetail(id) {
                this.$router.push('/rep/detail/'+id)
            }
        },
    }
</script>

<style scoped>
    .wm-banzhuren {
        height: 30px;
        margin: 10px 15px;
    }

    .wm-baodao {
        margin-top: 30px;
    }

    .wm-baodao p {
        font-size: 17px;
        font-weight: bold;
        color: #1989fa;
        margin: 10px 15px 5px;
        border-bottom: 1px solid #1989FA;
    }
</style>
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梅坞茶坊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值