基于开发风格统一的考虑,所有前端包括移动端的接口调用都要用自定义协议,我们设计的自定义协议分为固定部分protocol和参数部分param。Vue-element-admin模板中的参数都是散装的,如果我们都要给他们构建一个符合要求的数据结构,那工作量是令人恐怖的。以login部分的数据结构为例。
在/view/login中关于表单数据的定义是这样的:
loginForm: {
username: "chris",
password: "123456"
},
调用逻辑是这样的:
handleLogin() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true;
this.$store
.dispatch("accountLogin", this.loginForm)
.then(() => {
this.loading = false;
setCookie("username", this.loginForm.username, 15);
setCookie("password", this.loginForm.password, 15);
this.$router.push({ path: "/" });
})
.catch(() => {
this.loading = false;
});
} else {
console.log("参数验证不合法!");
return false;
}
});
},
/api/login.js中的接口调用是这样设计的:
export function login(param) {
return request({
url: '/uaa/api/account/login',
method: 'post',
data: param
})
}
/store/user.js中的登录action是这样的:
// 登录
accountLogin({ commit }, param) {
return new Promise((resolve, reject) => {
login(param).then(response => {
const tokenStr = response.data.accessToken
setToken(tokenStr)
commit('SET_TOKEN', tokenStr)
console.log(tokenStr);
resolve()
}).catch(error => {
reject(error)
})
})
},
这样的调用是干干净净的请求参数,没有包裹我们的自定义协议。如果把数据结构改成需要的,就是这样:
{
protocol: {
os: 'web',
ver: '1.0',
channel: 1,
token: 'none',
clientId: 'minur-mall-app',
clientSecret: 'minur-mall-app-secret',
lng: 121.123456,
lat: 31.123456
},
param: {
username: "chris",
password: "123456"
}
}
因为我们要在后端验证调用权限,所以每次调用都要这么包裹。但是,如果只是一两次还好,如果几百个接口的调用都要这样做,那就有点恐怖了。还好,做网络编程的都知道拦截器,我们在拦截器中做一点设置就好了。
在/utils/request.js中配置request拦截器:
// request拦截器
service.interceptors.request.use(config => {
if (store.getters.token) {
// 让每个请求携带自定义token 请根据实际情况自行修改
config.headers['Authorization'] = "Bearer " + getToken()
}
// 给每一次的post请求加上自定义协议包裹
if (config.method === 'post' && config.data !== null) {
config.data = {
protocol: {
os: 'web',
ver: '1.0',
channel: 1,
token: 'no',
clientId: 'minur-mall-app',
clientSecret: 'minur-mall-app-secret',
lng: 121.123456,
lat: 31.123456
},
param: config.data
}
}
return config
}, error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
})
其中的config.data就是我们封装的参数体requestBody部分,我们重构一下,把原来的数据放到param部分就可以了。