注意:我是負責前端部分的,後端是同學在負責,所以我只負責一個前後端的對接。背景是一個在線商城。
前端部分
首先清楚前端是作爲客戶端,請求後端服務端的消息。所以前端後端都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踩坑的錯誤寫法:
- 第一種:多寫了pathRewrite。
配置部分:
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。
- 那按道理來說這裏配置代理可以不設置成/goods,而設置成別的也行,比如我設置了一個/api,自動被識別成代理,然後和get的拼接起來。但是實際上是不可以的。無聊pathrewrite是否被註釋都不可以。
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',
)
曾經遇到這個問題就是CCORS_ORIGIN_WHITELIST中加了http導致的。