問題描述:
使用 Vue-cli 創建的項目,開發地址是 localhost:8080,需要訪問 localhost:9000 或https://m.maoyan.com或http://image.baidu.com上的接口
分析原因:
不同域名之間的訪問,需要跨域才能正確請求。跨域的方法很多,通常都需要后台配置
不過 Vue-cli 創建的項目,可以直接利用 Node.js 代理服務器,實現跨域請求
如果使用了 axios,可以全局配置一個 baseURL,這樣就不用挨個兒修改 url 了
axios.defaults.baseURL = '/api'
大家經常用的方法:
在 config>index.js 的 dev 中添加配置項 proxyTable:
proxyTable: { //本地調試 '/api': { //這里是我配置的名字 target: 'http://m.maoyan.com', //你要請求的第三方接口 changeOrigin: true, //開啟代理:在本地會創建一個虛擬服務端,然后發送請求的數據,並同時接收請求的數據,這樣服務端和服務端進行數據的交互就不會有跨域問題 pathRewrite: {'^/api': '/'} //這里重寫路徑運行后就代理到對應地址 /* 想請求接口是 http://m.maoyan.com/ajax/movieOnInfoList?token= target 是 目標服務器地址 本地代理服務器請求數據的時候它會把我們本地的 http:localhost:8080 替換成 http://m.maoyan.com changeOrigin: true, //開啟代理:在本地會創建一個虛擬服務端,然后發送請求的數據,並同時接收請求的數據,這樣服務端和服務端進行數據的交互就不會有跨域問題 pathRewrite: {'^/api': '/'} //這里重寫路徑運行后就代理到對應地址 如果不寫這個.我們本請求的路徑是 /api/ajax/movieOnInfoList?token= , 本地代理服務器補全路徑后 就是 http:localhost:8080/api/ajax/movieOnInfoList?token= 這和原 接口地址 比較 是 域名不一樣(這個在target已經處理過了, 相當於一樣了) , 還多了一個 /api,所 以我們要把他處理掉, 通過pathRewrite: {'^/api': '/'} ,意思是 把 '/api' 替換成 '/', 這樣 本地代理服務器請求地址就變成 http:localhost:8080//ajax/movieOnInfoList?token= (接口於接口之間多寫/ 沒事會自動處理掉,上面也可以寫成 pathRewrite: {'^/api': ''} ), 但是這樣寫不好, 接口於接口之間放個空 語義不強, 所以建議放個 '/' */ } },
經過上面的配置就可以這樣去請求 https:m.maoyan.com 上的接口了。
async mounted(){ let data = await data = await this.$http.get('/api/ajax/movieOnInfoList?token='); console.log(data); }
我這里$http就是axios, 因為我這里把axios掛載到了vue實例上,並重命名為 $http
import axios from 'axios' //引入 axios 異步請求工具 插件 import store from './store'; Vue.prototype.$http = axios; // 把 axios 方法 通過 原型 掛載 到vue根實例上(自定義key值為$http,vue實例也是一個對象嘛,所以可以自定義), // 這樣 在vue項目里哪里都可以用了,不用單個mport axios from 'axios' 引入了。 //就可以以 this.$http.get().then(function(){}).catch(function(){}) 的形式去使用了,post 請求類似 get請求。
這樣對只跨域請求一個域名上的數據,就完成了。當時我們有時候要跨域請求多個域名怎么辦呢?
例如: 我們即要請求 https://m.maoyan.com上的接口,又要請求 http://image.baidu.com上的接口。
這是后我們這要再配一個就代理就行了。代碼如下:
proxyTable: { //本地調試 '/api': { //這里是我配置的名字 target: 'http://m.maoyan.com', //你要請求的第三方接口 changeOrigin: true, //開啟代理:在本地會創建一個虛擬服務端,然后發送請求的數據,並同時接收請求的數據,這樣服務端和服務端進行數據的交互就不會有跨域問題 pathRewrite: {'^/api': '/'} //這里重寫路徑運行后就代理到對應地址 /* 想請求接口是 http://m.maoyan.com/ajax/movieOnInfoList?token= target 是 目標服務器地址 本地代理服務器請求數據的時候它會把我們本地的 http:localhost:8080 替換成 http://m.maoyan.com changeOrigin: true, //開啟代理:在本地會創建一個虛擬服務端,然后發送請求的數據,並同時接收請求的數據,這樣服務端和服務端進行數據的交互就不會有跨域問題 pathRewrite: {'^/api': '/'} //這里重寫路徑運行后就代理到對應地址 如果不寫這個.我們本請求的路徑是 /api/ajax/movieOnInfoList?token= , 本地代理服務器補全路徑后 就是 http:localhost:8080/api/ajax/movieOnInfoList?token= 這和原 接口地址 比較 是 域名不一樣(這個在target已經處理過了, 相當於一樣了) , 還多了一個 /api,所 以我們要把他處理掉, 通過pathRewrite: {'^/api': '/'} ,意思是 把 '/api' 替換成 '/', 這樣 本地代理服務器請求地址就變成 http:localhost:8080//ajax/movieOnInfoList?token= (接口於接口之間多寫/ 沒事會自動處理掉,上面也可以寫成 pathRewrite: {'^/api': ''} ), 但是這樣寫不好, 接口於接口之間放個空 語義不強, 所以建議放個 '/' */ }, //因為我們 登錄頁的 請求接口 是 https://i.meituan.com 所以我們要在配一個代理: //本地調試 /* 注意這里不能用 '/api/baidu' 因為 這樣當你到調用的時候 (原始接口: http://image.baidu.com/search/wisejsonala?tn=wisejsonala&ie=utf8&cur=result&word=%E6%91%84%E5%BD%B1%E5%B8%88%E9%99%88%E7%A3%8A&fr=&catename=&pn=0&rn=3&gsm=1e000000001e ) 你調用的是后 會這樣寫 this.$http.get('/api/baidu/search/wisejsonala?tn=wisejsonala&ie=utf8&cur=result&word=%E6%91%84%E5%BD%B1%E5%B8%88%E9%99%88%E7%A3%8A&fr=&catename=&pn=0&rn=3&gsm=1e000000001e') 這樣就 會先匹配到 '/api' 這個暗號,代理請求到 http://m.maoyan.com, 但這並不是我們想要的,所以我們得重新寫一個區別於上上面的暗號。 因為這個地方因為個人愛好的問題。 要統一寫 '/api' 這個形式,可以把 貓眼域名 的暗號 改成 '/api/maoyan', 把 百度域名的暗號 改成 '/api/baidu' 這樣就有統一的入口 '/api' 了。 我這里不統一改了。因為上面 的 '/api' 用的地方挺多的,這里一改,其他地方也要動。 統一管理的代碼: '/api/maoyan': { //這里是我配置的名字 target: 'http://m.maoyan.com', //你要請求的第三方接口 changeOrigin: true, //開啟代理:在本地會創建一個虛擬服務端,然后發送請求的數據,並同時接收請求的數據,這樣服務端和服務端進行數據的交互就不會有跨域問題 pathRewrite: {'^/api/maoyan': '/'} //這里重寫路徑運行后就代理到對應地址 }, '/api/baidu': { //這里是我配置的名字 target: 'http://image.baidu.com', //你要請求的第三方接口 changeOrigin: true, //開啟代理:在本地會創建一個虛擬服務端,然后發送請求的數據,並同時接收請求的數據,這樣服務端和服務端進行數據的交互就不會有跨域問題 pathRewrite: {'^/api/baidu': '/'} //這里重寫路徑運行后就代理到對應地址 } 使用時: 1: this.$http.get('/api/maoyan/ajax/movieOnInfoList?token='); 2: this.$http.get('/api/baidu/search/wisejsonala?tn=wisejsonala&ie=utf8&cur=result&word=%E6%91%84%E5%BD%B1%E5%B8%88%E9%99%88%E7%A3%8A&fr=&catename=&pn=0&rn=3&gsm=1e000000001e'); */ '/baidu': { //這里是我配置的名字 target: 'http://image.baidu.com', //你要請求的第三方接口 changeOrigin: true, //開啟代理:在本地會創建一個虛擬服務端,然后發送請求的數據,並同時接收請求的數據,這樣服務端和服務端進行數據的交互就不會有跨域問題 pathRewrite: {'^/baidu': '/'} //這里重寫路徑運行后就代理到對應地址 } },
測試使用'/baidu' :
async mounted(){ // let data = await this.$http.post('https://i.meituan.com/account/custom/mobilelogincode2'); let data = await this.$http.get('/baidu/search/wisejsonala?tn=wisejsonala&ie=utf8&cur=result&word=%E6%91%84%E5%BD%B1%E5%B8%88%E9%99%88%E7%A3%8A&fr=&catename=&pn=0&rn=3&gsm=1e000000001e'); console.log(data); }
輸出:
成功了。
上面注釋挺多的,可能看着眼暈,我在附一張簡單 的。
這樣就實現了跨域向多個域名請求了。