注意:我是负责前端部分的,后端是同学在负责,所以我只负责一个前后端的对接。背景是一个在线商城。
首先清楚前端是作为客户端,请求后端服务端的消息。所以前端后端都run起来。
后端的同学给了我这样的接口文档:
因此后端请求这个url就能够返回数据:
接下来是前端的问题,前端就是要向这个URL发出get的请求。
这里我使用了axios的包,首先npm install axios
,然后在/src/api/index.js下对axios做配置:
import axios from 'axios';
import Qs from 'qs'; // 用来处理参数,可不使用,若要使用,npm安装: npm install qs
axios.defaults.baseURL = 'http://127.0.0.1:8000/'; // 请求的默认域名
// 添加一个请求拦截器
axios.interceptors.request.use(config => {
config.headers.languagetype = 'CN'; // 举例,加上一个公共头部
config.data = Qs.stringify(config.data); // 处理数据,可不写
return config;
},
err => {
return Promise.reject(err);
});
//添加一个响应拦截器
axios.interceptors.response.use(res => {
//在这里对返回的数据进行处理
console.log(res.data, '网络正常');
return res.data;
}, err => {
console.log('网络开了小差!请重试...');
return Promise.reject(err);
});
export default axios
然后在main.js的地方全局引入,注意这里的axios是灰色的,因为Unused definition $axios
,但是无所谓:
Vue.prototype.$axios = Axios; //全局注册,使用方法为:this.$axios
Vue.config.productionTip = false;
接下来就可以在任何一个vue中直接通过this.$axios引用了:
methods:{
//params是添加到url的请求字符串中的,用于get请求, 参数是以id=124&name=jerry的形式附到url的后面
// 而data是添加到请求体(body)中的, 用于post请求。
test(){
this.items = this.$axios({
method: "get",
url: "/goods/ListItem", // 接口地址
// data: {
// keyword: "1" // 传接口参数
// }
})
.then(response => {
console.log(response, "success"); // 成功的返回
})
.catch(error => console.log(error, "error")); // 失败的返
}
}
但是此时有一个很严重的错误发生了,作为服务器的Django和vue产生了一个跨域的问题,浏览器禁止跨域访问:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/goods/ListItem' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
我一开始天真的认为改变一下vue服务器的端口就行,于是在根目录下创建了vue.config.js,想把软口也设置成8000,但是8000其实已经被Django占用了,所以会自动改成8001端口,所以跨域问题是必须要解决的了:
module.exports = {
devServer: {
disableHostCheck: true,
host:'127.0.0.1',
port: 8000,
},
lintOnSave: false
}
于是我修改成这样,但是即使这样还是会报404,并且还是用本地的地址:
中间经历了几天的波折才弄懂。
首先main.js一定要引入baseURL,如果不引入或者为空Django的服务器端是无法收到请求的:
axios.defaults.baseURL = '/goods';
然后vue.config.js里面配置,注意我这里是proxy而不是proxytable。host和port都是设置vue端的服务器地址和端口。
module.exports = {
devServer: {
host: '127.0.0.1',
port: 8080,
open: true,
proxy: {//配置跨域
'/goods': {
target: 'http://127.0.0.1:8000',//这里后台的地址,应该填写你们真实的后台接口
ws: true,
secure: false,//https则是ture
changOrigin: true,//允许跨域
// pathRewrite: {
// '^/goods': ''
// }
},
}
}
};
然后使用axios在组件中实现跨域,我要访问的具体地址是http://127.0.0.1:8000/goods/ListItem:
this.axios.get("/goods/ListItem")
.then(response => {
if (response.data) {
console.log(response.data)
}
})
.catch(error => {
alert(error)
})
axios踩坑的错误写法:
module.exports = {
devServer: {
host: '127.0.0.1',
// NODE_ENV: 'production',//生产环境
port: 8080,
open: true,
proxy: {//配置跨域
'/goods': {
target: 'http://127.0.0.1:8000',//这里后台的地址模拟的;应该填写你们真实的后台接口
ws: true,
secure: false,
changOrigin: true,//允许跨域
pathRewrite: {
'^/goods': ''
}
},
}
}
};
main.js:
axios.defaults.baseURL = '/goods';
使用:
this.axios.get("/goods/ListItem")
此时后台接受的消息显然是将使用的/goods替换成了’ '。虽然看起来应该是baseurl+/goods/ListItem,但是实际上显然baseurl被替换成了proxy下的/goods的target。
axios.defaults.baseURL = '/api';
module.exports = {
devServer: {
host: '127.0.0.1',
// NODE_ENV: 'production',//生产环境
port: 8080,
open: true,
proxy: {//配置跨域
'/api': {
target: 'http://127.0.0.1:8000',//这里后台的地址模拟的;应该填写你们真实的后台接口
ws: true,
secure: false,
changOrigin: true,//允许跨域
// pathRewrite: {
// '^/goods': ''
// }
},
}
}
};
this.axios.get("/goods/ListItem")
也就是说,想要代理成功,必须代理的地址必须和代理的api一致才行。比如我要访问的是/goods/listitem/,我必须设置的代理是/goods。
接下来是对Django的设置。首先先安装conda install django-cors-headers
。
然后在settings.py里修改配置。
在导入的模块里加入corsheaders:
INSTALLED_APPS = [
'store_db',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 跨域设计
'corsheaders'
]
然后在中间件加入’corsheaders.middleware.CorsMiddleware’:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', # 注意顺序,必须放在这儿
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
最后加入:
#开启debug模式,注意上线运营时要关闭debug
DEBUG = True
# 允许所有ip访问
ALLOWED_HOSTS = ['*']
#跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
if DEBUG:
CORS_ORIGIN_ALLOW_ALL = True
else:
CCORS_ORIGIN_WHITELIST = (
//注意这里不能加http
'127.0.0.1:8080'
)
# 允许的请求头
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
)