vue 2 JS中使用vuex的Axios拦截器 [英] Axios interceptor in vue 2 JS using vuex

查看:36
本文介绍了vue 2 JS中使用vuex的Axios拦截器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 vuex 商店中成功登录调用后存储令牌,如下所示:

I store token after success login call in vuex store like this:

axios.post('/api/auth/doLogin.php', params, axiosConfig)
    .then(res => {
        console.log(res.data); // token
        this.$store.commit('login', res.data);
    })

axiosConfig 是我只设置 baseURL 的文件 export default { baseURL: 'http://localhost/obiezaca/v2' } 和 params 只是发送到后端的数据.

axiosConfig is file where I only set baseURL export default { baseURL: 'http://localhost/obiezaca/v2' } and params is just data sent to backend.

我的 vuex 文件看起来是:

My vuex file looks is:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export const store = new Vuex.Store({
    state: {
        logged: false,
        token: ''
    },
    mutations: {
        login: (state, response) => {
            state.logged = true;
            state.token = response;
            console.log('state updated');
            console.log('state.logged flag is: '+state.logged);
            console.log('state.token: '+state.token);
        },
        logout: (state) => {
            state.logged = false;
            state.token = '';
        }
    }
});

它工作正常,我可以根据登录用户的 v-if="this.$store.state.logged" 在我的 SPA 中重新渲染一些内容.我可以从整个应用程序中的任何组件访问 this.$store.state.logged.

It is working correctly, I can re-render some of content in my SPA basing on v-if="this.$store.state.logged" for logged user. I'm able to access this.$store.state.logged from any component in my entire app.

现在我想将我的令牌添加到调用我的 rest API 后端的每个请求中.我创建了基本的 axios http 拦截器,如下所示:

Now I want to add my token to every request which call my rest API backend. I've created basic axios http interceptor which looks like this:

import axios from 'axios';

axios.interceptors.request.use(function(config) {
    const token = this.$store.state.token;
    if(token) {
        config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
}, function(err) {
    return Promise.reject(err);
});

现在我有两个问题/疑问.

Now I have 2 problems/questions about it.

  1. 我知道可以在每个组件中使用 this.$store.state.loggedthis.$store.state.token 但我可以使用它吗在单个 javascript 文件中的方式相同吗?
  2. 我应该在哪里执行/启动我的拦截器 javascript 文件?它是位于我的应用程序主文件夹中的独立文件,但我没有在任何地方调用它,在我之前工作的 angularJS 中,我不得不添加 $httpProvider.interceptors.push('authInterceptorService');在配置中,但我不知道如何在 vue 架构中做同样的事情.那么我应该在哪里注入拦截器?
  1. I know that it is available to use this.$store.state.logged or this.$store.state.token across every component but can I use it same way in single javascript file?
  2. Where should I execute/start my interceptor javascript file? It is independent file which lays in my app main folder but I am not calling it anywhere, in angularJS which I was working before, I had to add $httpProvider.interceptors.push('authInterceptorService'); in config but I don't know how to do same thing in vue architecture. So where should I inject my interceptor?

编辑

我遵循了GMaiolo我添加的提示

import interceptor from './helpers/httpInterceptor.js';
interceptor();

到我的 main.js 文件,我将拦截器重构为:

to my main.js file and I refactor my interceptor to this:

import axios from 'axios';
import store from '../store/store';

export default function execute() {
    axios.interceptors.request.use(function(config) {
        const token = this.$store.state.token;
        if(token) {
            config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
    }, function(err) {
        return Promise.reject(err);
    });
}

此更改的结果是,每个现有的不需要令牌即可工作的后端调用 ( GET ) 停止工作,但这是合乎逻辑的,因为我没有说明应该向哪个请求添加令牌,因此它正在尝试添加它无处不在,在我的拦截器中仍然有问题,这就是为什么每个已经存在的请求都停止工作的原因.

Result of this changes is that every already existing backend calls ( GET ) which don't need token to work stopped working but it is logical because I didn't clarified to which request it should add token so it is trying to add it everywhere and in my interceptor something is still wrong and that is why every already exisitng request stopped working.

当我尝试在浏览器控制台中进行后端 POST 调用时,我仍然收到此错误:

When I try to do backend POST call in browser console I still get this error:

TypeError: 无法读取未定义的属性 '$store'

TypeError: Cannot read property '$store' of undefined

虽然我将 store 导入到我的拦截器文件中.有任何想法吗?如果需要,我可以提供更多信息.

Although I import store to my interceptor file. Any ideas? I can provide some more information if any needed.

我另外添加了这个主要的、存储的和拦截器树结构的截图,所以你可以看到我是从正确的路径导入的:

I additionally add screenshot of this main, store and interceptor tree structure so you can see that I'm importing fron correct path:

推荐答案

1.

首先我会使用 Vuex 模块 作为这个登录/会话行为似乎是 Session 模块的理想选择.之后(完全可选)你可以设置一个 Getter 来避免访问 Gettercode>state 本身来自 Vuex 之外,你最终会得到这样的结果:

1.

First of all I'd use a Vuex Module as this Login/Session behavior seems to be ideal for a Session module. After that (which is totally optional) you can set up a Getter to avoid accessing the state itself from outside Vuex, you'd would end up with something like this:

state: {
  // bear in mind i'm not using a module here for the sake of simplicity
  session: {
    logged: false,
    token: ''
  } 
},
getters: {
  // could use only this getter and use it for both token and logged
  session: state => state.session,
  // or could have both getters separated
  logged: state => state.session.logged,
  token: state => state.session.token
},
mutations: {
  ...
}

设置这些 getter 后,您可以更轻松地从组件中获取值.使用 this.$store.getters.logged(或您想要使用的那个)或使用 Vuex 的 mapGetters 助手 [有关此的更多信息,您可以检查 getters 文档]:

With those getters set, you can get the values a bit easier from components. With either using this.$store.getters.logged (or the one you'd want to use) or using the mapGetters helper from Vuex [for more info about this you can check the getters docs]:

import { mapGetters } from 'vuex'
export default {
  // ...
  computed: {
    ...mapGetters([
      'logged',
      'token'
    ])
  }
}

2.

我喜欢在 main.js 创建、导入和执行一个 interceptors.js 帮助程序时运行 Axios 的拦截器和 Vue 实例化.我会留下一个例子让你有个想法,但是,再说一次,这是我自己的偏好:

2.

I like to run Axios' interceptors along with Vue instantation in main.js creating, importing and executing an interceptors.js helper. I'd leave an example so you get an idea, but, then again, this is my own preference:

ma​​in.js

import Vue from 'vue';
import store from 'Src/store';
import router from 'Src/router';
import App from 'Src/App';

// importing the helper
import interceptorsSetup from 'Src/helpers/interceptors'

// and running it somewhere here
interceptorsSetup()

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    store,
    template: '<App/>',
    components: { App }
});

interceptors.js

import axios from 'axios';
import store from 'your/store/path/store'

export default function setup() {
    axios.interceptors.request.use(function(config) {
        const token = store.getters.token;
        if(token) {
            config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
    }, function(err) {
        return Promise.reject(err);
    });
}

这样你就可以清楚地封装所有的行为.

And there you'd end up having all the behavior cleanly encapsulated.

这篇关于vue 2 JS中使用vuex的Axios拦截器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆