传给后端的两种数据格式区别
解: 1:请求为get的时候,参数在URL中。
2:请求为post的时候在请求body中,这里有两种方式(json和form的字符串),取决于后端需要哪一种方式。后一种方式需要使用qs.stringify()转换。
(1) service.defaults.headers.post['Content-Type'] = 'application/json' .这种是默认的,所以不用设置。
(2)config.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'. 这种是字符串的方式。
转换方式:
3: 完整 request.js代码,可以直接引用.(包括了统一loading、重复请求的处理、错误的提示)
import axios from 'axios'
import qs from 'qs'
import store from '../store'
import { Toast } from 'vant'
// 根据发布到服务器的地址作为域名和端口,到时拼接对应的接口文件路径
function getBaseURL(){
let server = '/api'
if (process.env.NODE_ENV === 'production') {
server = window.location.protocol + '//' + window.location.host
}
return server
}
// 设置axios的基本配置
const service = axios.create({
baseURL: getBaseURL(), // 接口的基本路径
withCredentials: true, // 发送cookie到后端跨域的时候
timeout: 50000 // 请求过期时间为5s
})
let loadingRequestCount = 0;
// loading打开
const showLoading = () =>{
if (loadingRequestCount === 0) {
store.dispatch('showLoadingStatus')
}
loadingRequestCount++
}
const hideLoading = () => {
if (loadingRequestCount <= 0) return
loadingRequestCount--
if (loadingRequestCount === 0) {
vue.$nextTick(()=>{//以服务的方式调用的 Loading 需要异步关闭
store.dispatch('closeLoadingStatus')
})
}
}
// 解决按钮快速点击重复请求的问题
const CancelToken = axios.CancelToken
let configUrls = []
let removePending = (config) =>{
configUrls.forEach((item,index)=>{
if(item.name === config.url+'&'+config.method){
item.f()
configUrls.splice(index,1)
}
})
}
service.defaults.headers.post['Content-Type'] = 'application/json'
// service.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
service.interceptors.request.use(config => {
removePending(config)
config.cancelToken = new CancelToken((cancel)=>{
configUrls.push({name: config.url+'&'+config.method, f: cancel})
})
if (store.getters.token) {
config.headers['Authorization'] = JSON.stringify({ 'token': store.getters.token })
config.headers['clientInfo'] = getClientInfo()
}
// 请求拦截进来调用显示loading效果
showLoading(config)
return config
}, error => {
Toast.fail('请求异常 ' + error.message)
return Promise.reject(error)
})
service.interceptors.response.use(response => {
removePending(response.config)
const res = response.data
// 响应拦截进来隐藏loading效果,此处采用延时处理是合并loading请求效果,避免多次请求loading关闭又开启
setTimeout(() => {
hideLoading()
}, 200)
// 成功返回数据
if (res.code === 200) {
return res
}
// 一般这里返回其它状态的时候写其它函数操作,例如退出登录
}, error => {
// 响应拦截进来隐藏loading效果,此处采用延时处理是合并loading请求效果,避免多次请求loading关闭又开启
setTimeout(() => {
hideLoading()
}, 200)
// 弹出报错的信息
if (error.response) {
code = error.response.status
} else {
code = '网络已断开'
}
Toast.fail('网络开小差(' + code + ')')
return Promise.reject(error)
})
export default service
loading.vue组件 引用vant vue
<template>
<div class="loading">
<van-loading size="74px" type="spinner" color="#1989fa" vertical><span style="color:#1989fa;">加载中...</span></van-loading>
</div>
</template>
<script>
export default {
name: 'LOADING',
data () {
return {}
},
}
</script>
<style scoped>
.loading{
position: fixed;
top:0;
left:0;
z-index:121;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.1);
display: flex;
align-items: center;
justify-content: center;
}
.loading img{
width: 1rem;
height: 1rem;
margin:7.5rem auto;
}
</style>
store组件 action
const actions = {
setName({ commit }, name) {
commit('SET_NAME', name)
},
showLoadingStatus:({ commit }, status) => {
commit('SET_LOADING_STATUS', true)
},
closeLoadingStatus:({ commit }, status) => {
commit('SET_LOADING_STATUS', false)
},
}
export default actions