前言
寫專案,跨域永遠是個繞不開的問題,除非自己在localhost上玩.以前總是後端用cors的方式去解決這個問題.老問題,後端如果沒整,怎麼玩?寫vue專案,常用vue-cli工具依照webpack模板去搭一個專案結構.每個人都知道用npm run dev 啟動專案,但是更應該知道的是我們是依賴了webpack-dev-server代理伺服器(用node.js寫的)才啟動了這個專案.沒親手設定可不代表不存在.所以才會在vue專案中有伺服器代理這種配置項.補一句:二手資料害死人.
問題描述:
使用 Vue-cli 建立的專案,(前端)開發地址是 localhost:8080,需要訪問 (後端)上的介面並不是這個,例如後端地址是http://192.168.199.168:8080/ ,資料訪問是要跨域的喲!
抄來的方案:(先說說網上抄來抄去的一個手法)
1.在 config資料夾下index.js檔案 的 dev 中新增配置項 proxyTable:
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
// 我們家的介面就不用api這種字首,要怎樣
'/api': {
target: 'http://192.168.199.168:8080/',
changeOrigin: true,
// 為什麼不能說說pathRewrite到底是幹什麼的呢
// 就知道要'^/api': '/'或者'^/api': '/'
// 以及'/'和''有什麼區別
// 哎,二手資料害死人
pathRewrite: {
'^/api': '/'
}
}
},
複製程式碼
2.使用axios外掛時,發的請求
axios.get('/api/yyd-manage/department/list')
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
複製程式碼
注:
1.使用了 axios,可以全域性配置一個 baseURL,這樣就不用挨個兒修改 url 了,可以省掉請求時的'/api',如:axios.get('/yyd-manage/department/list').
axios.defaults.baseURL = '/api'
//放在main.js檔案中或者自己寫一個js外掛檔案,在main.js中註冊一下
複製程式碼
這種手法可去你的吧,這屬於強行操作
2.其中 '/api' 為匹配項,target 為被請求的地址
3.因為在 ajax 的 url 中加了字首 '/api',而原本的介面是沒有這個字首的 所以需要通過 pathRewrite 來重寫地址,將字首 '/api' 轉為 '/' 如果本身的介面地址就有 '/api' 這種通用字首,就可以把 pathRewrite 刪掉
上述操作全屬於無腦抄襲,也就能騙騙我這種水貨,完全不具備實用性
解決方案:
先看後端node伺服器的一段簡易程式碼
/*
express框架是nodeJS的第三方模組 express框架實際上是對http模組的高度封裝
*/
// 相當於引入了http模組
const express = require('express');
// 建立web伺服器
const app = express();
// 當客戶端以get方式請求/的時候
app.get('/index', (req, res) => {
// express提供給我們的用來做響應的方法
res.send('首頁')
})
app.get('/list', (req, res) => {
res.send('列表頁')
})
app.get('/article', (req, res) => {
res.send('文章頁')
})
app.post('/getUserInfo', (rep, res) => {
res.send('使用者詳情');
})
// 監聽埠
app.listen(3000, () => {
console.log('伺服器啟動成功');
});
複製程式碼
例:其中的一個介面地址為:http://localhost:3000/index
vue-cli搭的webpack專案模板中前端設定伺服器代理的程式碼
//在 config資料夾下index.js檔案 的 dev 中新增配置項 proxyTable
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/index': {
target: 'http://localhost:3000/',
changeOrigin: true,
// 就不寫pathRewrite
}
},
複製程式碼
axios的get別名請求方法程式碼
//隨便找個元件寫個點選事件,發請求
axios.get('/index')
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
})
複製程式碼
返回內容(跨域成功)
並沒有什麼api,也沒有pathRewrite: {"^/api" : ""}照樣能使用注:
1.proxyTable中的'/index'相當於一個標識,告訴webpack-dev-server,我的請求介面中以/index開頭的地址要使用代理.不然的話, 可能你的 html, css, js這些靜態資源都跑去代理. 所以我們只要介面用代理, 靜態檔案用本地.極端情況下你使用'/',那麼所有的請求都會被代理,當然也可以正常跨域.
2.使用這種伺服器代理的方式跨域時,不需要再去設定axios的基地址了,會報錯. 即不用axios.get('http://localhost:3000/index')也不用axios.defaults.baseURL = 'http://localhost:3000/' 然後axios.get('/index')
3.proxyTable的配置項是webpack模板作者自己定義的,實際上真正生效的是webpack的devServer.proxy配置項,在build資料夾下webpack.dev.conf.js可以看到proxy: config.dev.proxyTable
,靠這行程式碼實現的真正配置.iview-admin模板的vue.config.js中正是直接使用devServer.proxy而不是proxyTable,才讓我在兩個專案模板上困惑不已.
參考文章:vue-cli的webpack相關內容
參考文章:webpack的DevServer
4.pathRewrite的作用:
pathRewrite相當於一個重定向或者叫重寫請求路徑的作用,當然也可以移除,新增.
這是隸屬於外掛http-proxy-middleware的東西,該外掛功能強大,還有路由等功能.
上一段配置程式碼(修改配置項要注意重啟專案)
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/index': {
target: 'http://localhost:3000/',
changeOrigin: true,
pathRewrite: {
// 符號^是正規表示式符號,是匹配輸入字串的開始位置
'^/index': '/list'
}
}
},
複製程式碼
本來我們要請求http://localhost:3000/index的介面現在就成了請求http://localhost:3000/list
axios的get別名請求方法程式碼
//隨便找個元件寫個點選事件,發請求
axios.get('/index')
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
})
複製程式碼
返回結果(是介面/list的結果,而不是/index的)
專案中的配置檔案還是應當好好研究一下,不僅僅是跨域問題,還有開發模式,測試模式,生產模式,process.env等環境變數,路還很遠.明年就要正式更新vue3.0了,變化真快.