使用vuex的vue 2 JS中的axios拦截器
Axios interceptor in vue 2 JS using vuex
我在 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 个 problems/questions 了。
- 我知道可以在每个组件中使用
this.$store.state.logged
或 this.$store.state.token
,但我可以在单个 javascript 文件中以相同的方式使用它吗?
- 我应该 execute/start 我的拦截器 javascript 文件在哪里?它是位于我的应用程序主文件夹中的独立文件,但我没有在任何地方调用它,在我之前工作的 angularJS 中,我不得不在配置中添加
$httpProvider.interceptors.push('authInterceptorService');
但我不知道如何在 vue 架构中做同样的事情。那么我应该在哪里注入我的拦截器呢?
编辑
我遵循了 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: Cannot read property '$store' of undefined
尽管我将商店导入到我的拦截器文件中。有任何想法吗?如果需要,我可以提供更多信息。
我还添加了这个主要、存储和拦截器树结构的屏幕截图,这样你就可以看到我正在从正确的路径导入:
1.
首先我会使用 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 来避免从 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.
我喜欢 运行 Axios 的拦截器以及 main.js
中的 Vue 实例化创建、导入和执行 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);
});
}
在那里你最终会把所有的行为都干净地封装起来。
我做了同样的逻辑。但是,我只是更改了文件名。我使用了 axios/index.js 但那里的商店未定义。所以我只是更改文件名 axios/interceptor.js 并且不知道存储数据是否可以访问 look at my below image
我在 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 个 problems/questions 了。
- 我知道可以在每个组件中使用
this.$store.state.logged
或this.$store.state.token
,但我可以在单个 javascript 文件中以相同的方式使用它吗? - 我应该 execute/start 我的拦截器 javascript 文件在哪里?它是位于我的应用程序主文件夹中的独立文件,但我没有在任何地方调用它,在我之前工作的 angularJS 中,我不得不在配置中添加
$httpProvider.interceptors.push('authInterceptorService');
但我不知道如何在 vue 架构中做同样的事情。那么我应该在哪里注入我的拦截器呢?
编辑
我遵循了 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: Cannot read property '$store' of undefined
尽管我将商店导入到我的拦截器文件中。有任何想法吗?如果需要,我可以提供更多信息。
我还添加了这个主要、存储和拦截器树结构的屏幕截图,这样你就可以看到我正在从正确的路径导入:
1.
首先我会使用 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 来避免从 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.
我喜欢 运行 Axios 的拦截器以及 main.js
中的 Vue 实例化创建、导入和执行 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);
});
}
在那里你最终会把所有的行为都干净地封装起来。
我做了同样的逻辑。但是,我只是更改了文件名。我使用了 axios/index.js 但那里的商店未定义。所以我只是更改文件名 axios/interceptor.js 并且不知道存储数据是否可以访问 look at my below image