总结笔者最近在项目中使用Vuex2和Axios的总结和小技巧,方便日后查看。本人能力有限,如有错误还请大大们指正探讨😭。
阅读前须知
接上一篇的Axios的配置,阅读本文默认您已经掌握了Vuex2的基本语法、Axios的使用配置与方法、Promise的基本语法。(下面将放出参考链接方便大家在有不明白的地方查看)此篇主要叙述我在实际项目过程中Vuex2和Axios的组合操作。
参考:
Vuex2中的Actions
在Vuex1中actions都可以统一使用dispatch去触发mutation,那时候去异步这种数据流没什么认识。在Vuex2中规定了,同步的方法使用commit去提交mutation,异步的方法(如接口请求,完成接口请求后的操作)只能通过分发action去触发,即使用dispatch。
这里不经吐槽2句,Vuex2的Api还是蛮人性化的,对比Redux为了用好单向数据流,不得不引入一大堆诸如react-redux、redux-saga、redux-thunk…,对新上手的小白来说简直是一脸蒙蔽。上面这些库所带的功能,用Vuex2都可以完成(手动骄傲),当然Vuex2也是站在这些巨人的肩膀上。
下面来看下vuex2中关于actions的API
类型: { [type: string]: Function }
在 store 上注册 action。处理函数接受一个 context 对象,包含以下属性:
{
state, // 等同于 store.state, 若在模块中则为局部状态
rootState, // 等同于 store.state, 只存在于模块中
commit, // 等同于 store.commit
dispatch, // 等同于 store.dispatch
getters // 等同于 store.getters
}
Axios的配置
这个是我项目内Axios的配置,主要做了下面几件事情
- 5秒的超时验证
- POST的设置
- 统一的response封装。我通过接口传回的CODE码去判断该请求是否正确
如果想去看更详细的解析可以通过Axios的配置
import axios from 'axios'
import qs from 'qs'
import * as _ from './whole' //alert
axios.defaults.timeout = 5000;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
axios.defaults.baseURL = 'http://xxx.xxx.com';
//POST传参序列化
axios.interceptors.request.use((config) => {
if(config.method === 'post'){
config.data = qs.stringify(config.data);
}
return config;
},(error) =>{
_.toast("错误的传参");
return Promise.reject(error);
});
//code状态码200判断
axios.interceptors.response.use((res) =>{
if(res.data.code != '200'){
_.toast(res.data.msg);
return Promise.reject(res);
}
return res;
}, (error) => {
_.toast("网络异常");
return Promise.reject(error);
});
export default axios;
完成一个请求操作
下面介绍一个登陆action的操作,
- 在接口发起请求时跳出loading
- 接口请求成功结束loading,并保存数据进入store
- 接口请求失败抛出异常,结束loading。
- 返回一个Promise对象,方便继续操作。
export const login = ({ commit },params) => {
_.busy(); //loding开始
return new Promise((resolve, reject)=> {
axios({
method:'get',
url: 'teacher/login',
params: {
moblie:params.mobile,
password:params.password,
}
})
.then((response) => {
commit(types.LOGIN,response.data.data); //获得的数据通过mutation,存入store中
_.leave(); //loding结束
resolve(response);
})
.catch((error) => {
_.leave(); //loding结束
})
});
}
const mutations = {
[types.LOGIN](state, data){
state.token = data.token;
}
}
//调用action
import { mapActions,mapGetters } from 'vuex'
export default {
methods:{
...mapActions(['login']), //注入action
_login(){
let params = {
mobile:this.mobile,
pwd:this.password
}
this.login(params).
then(()=>{
this.$router.replace('/main/index'); //正确完成后进入主页
})
.catch((error)=>{ //错误则清空密码文本框
//可以在这里对Error进行捕获,然后根据错误类型进行相对应的处理
this.pwd = '';
});
}
}
一点说明
因为在Vuex2中action可以直接拿到Store的值,所以我们可以通过 rootState这个参数拿到根的store值,通过state拿到当前模块中store的值
都没必要在从getter里拿到值,然后通过params的方式传入。
export const xxx = ({state,rootState,commit}) => {
return new Promise((resolve, reject)=> {
axios({
method:'get',
url: 'teacher/workbook/class/exercise',
params: {
"token":rootState.login.token, //从store根中拿到数据
"classCode":state.code, //从当前模块中拿到数据
"chapterId":rootState.route.params.chapterId
}
})
.then((response) => {
commit(types.WORKBOOK_CLASS_EXERCISE,response.data.data)
resolve(response);
})
});
}
这样是不是更方便我们去审查action的代码?