vue.js - 使用vuex的vue 2 JS中的axios拦截器

标签 vue.js vuejs2 axios interceptor vuex

我像这样在 vuex 存储中成功登录调用后存储 token :

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 只是发送到后端的数据。

我的 vuex 文件看起来是:

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

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

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);
});

现在我有 2 个问题/疑问。

  1. 我知道可以在每个组件中使用 this.$store.state.loggedthis.$store.state.token 但我可以使用它吗在单个 javascript 文件中采用相同的方式?
  2. 我应该在哪里执行/启动我的拦截器 javascript 文件?它是位于我的应用程序主文件夹中的独立文件,但我没有在任何地方调用它,在我之前工作的 angularJS 中,我必须添加 $httpProvider.interceptors.push('authInterceptorService');在配置中,但我不知道如何在 vue 架构中做同样的事情。那么我应该在哪里注入(inject)我的拦截器呢?

编辑

我遵循了我添加的 GMaiolo 技巧

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

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

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);
    });
}

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

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

TypeError: Cannot read property '$store' of undefined

尽管我将商店导入到我的拦截器文件中。有任何想法吗?如果需要,我可以提供更多信息。

我还添加了这个主要、存储和拦截器树结构的屏幕截图,这样您就可以看到我正在从正确的路径导入:

path

最佳答案

1.

首先我会使用 Vuex Module因为这种登录/ session 行为似乎是 Session 模块的理想选择。之后(这完全是可选的)你可以设置一个 Getter为了避免从 Vuex 外部访问 state 本身,你最终会得到这样的结果:

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 文档]:

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

2.

我喜欢在 main.js 中运行 Axios 的拦截器和 Vue 实例,创建、导入和执行 interceptors.js 助手。我会举一个例子让你明白,但话又说回来,这是我自己的偏好:

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 }
});

拦截器.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);
    });
}

在那里你最终会把所有的行为都干净地封装起来。

关于vue.js - 使用vuex的vue 2 JS中的axios拦截器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47946680/

相关文章:

javascript - vue.js - 如何监视嵌套对象的属性并获取索引?

javascript - 使用 Vue.js 的异步/等待 axios 调用

javascript - 仅当用户登录/本地存储存在时,如何授予对 Vue.js 中页面的访问权限?

javascript - 如何在 Vue.js 中删除 FullCalendar-4 事件

node.js - .then 之后逻辑不起作用

javascript - (良好的编程习惯)渲染中的两个返回是否正确?

reactjs - 单击按钮时,不会添加数据

javascript - 如何在 Vuetify 组件中以编程方式设置组件属性

javascript - Vue - 无法在 promise 中设置未定义的属性

laravel - vuejs组件中的用户php验证码