web-dev-qa-db-ja.com

vue 2 JSでvuexを使用したAxiosインターセプター

次のように、vuexストアにログイン呼び出しが成功した後、トークンを保存します

_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_にアクセスできます。

次に、残りの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.logged_または_this.$store.state.token_を使用できることを知っていますが、単一のJavaScriptファイルで同じように使用できますか?
  2. インターセプターjavascriptファイルはどこで実行/開始する必要がありますか?私のアプリのメインフォルダにある独立したファイルですが、どこでも呼び出していません。以前働いていたangularJSでは、設定に$httpProvider.interceptors.Push('authInterceptorService');を追加する必要がありましたが、同じ方法はわかりませんvue architecture。では、インターセプターをどこにインジェクトする必要がありますか?

[〜#〜] edit [〜#〜]

追加した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);
    });
}
_

この変更の結果、動作するためにトークンを必要としない既存のすべてのバックエンドコール(GET)は動作を停止しましたが、どのリクエストにトークンを追加する必要があるかを明確にしていないため、どこにでも追加しようとしています私のインターセプターでは何かがまだ間違っているため、すでに存在するすべてのリクエストが機能しなくなったのです。

バックエンドを実行しようとすると、POSTブラウザコンソールで呼び出しますが、このエラーが表示されます。

TypeError:未定義のプロパティ「$ store」を読み取ることができません

ストアをインターセプターファイルにインポートしますが。何か案は?必要に応じて、さらに情報を提供できます。

さらに、このメイン、ストア、インターセプターのツリー構造のスクリーンショットを追加して、正しいパスをインポートしていることを確認できるようにします。

path

18
dopeCode

1。

まず、 Vuex Module を使用します。このログイン/セッションの動作はSessionモジュールに理想的だと思われるためです。その後(完全にオプションです)、Vuexの外部からstate自体へのアクセスを回避するために Getter を設定できます。この:

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: {
  ...
}

これらのゲッターを設定すると、コンポーネントから値を少し簡単に取得できます。 this.$store.getters.logged(または使用するもの)を使用するか、VuexのmapGettersヘルパーを使用します[これについての詳細は、getters docsを確認してください。 ]:

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

2。

私はAxiosのインターセプターをVue main.jsのインスタンス化interceptors.jsヘルパーの作成、インポート、実行とともに実行するのが好きです。 、しかし、再び、これは私自身の好みです:

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

そして、すべての動作がきれいにカプセル化されることになります。

25
GMaiolo