vue中的跨域問題


https://segmentfault.com/a/1190000011072725(原文)

 

使用vue-axios和vue-resource解決vue中調用網易雲接口跨域的問題

注(api很重要,相當於攔截到api然后將api替換為index里的 target: 'http://news-at.zhihu.com/api',如果缺少了api也會報錯,404,但是看出不來到底啥原因

 

 

1.6 修改頁面內容

我們先修改一下頁面內容 src\components\Hello.vue

<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>{{ author }}</h2> </div> </template> <script> export default { name: 'hello', data () { return { msg: 'vue調用網易雲接口', author: '泥猴啊' } } } </script>

2. 使用axios

2.1 我們先修改一下頁面,讓頁面加載一些動態內容

模板修改如下

<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>{{ author }}</h2> <ul v-for="music in musics"> <li> {{ music.name }} </li> </ul> </div> </template>

js部分修改如下

<script>
export default { name: 'hello', data () { return { msg: 'vue調用網易雲接口', author: '泥猴啊', musics: [] } }, mounted: function () { axios.get('http://music.163.com/api/playlist/detail?id=19723756') .then(function (res) { console.log(res) }, function (error) { console.log(error) }) } } </script>

_

然后保存

發現頁面有一個報錯
http://eslint.org/docs/rules/no-undef 'axios' is not defined

axios沒有定義,是因為我們沒有導入axios模塊的原因

我們在js部分頂部導入一下axios模塊

import axios from 'axios'

加載axios模塊之后錯誤提示消失了。
打開調試頁面console界面
發現有一個報錯

No 'Access-Control-Allow-Origin' header is present on the requested resource.Origin 'http://localhost:8080' is therefore not allowed access.

這里的not allowed access就是提示我們瀏覽器不支持跨域請求,搜索了很多資料,網易雲不支持跨域請求的(網易雲的服務器在返回你的請求中沒有Access-Control-Allow-Origin這個head字段)。

那怎么辦呢?
那我們只能使用代理了。

下面將介紹3種代理方式:1,遠程代理 2,php代理 3,node代理

3 代理

3.1 遠程代理

就是利用別人寫好的代理接口,代理發送你的請求,這樣就不會跨域了。

首先我們定義一個常量API_PROXY

const API_PROXY = 'https://bird.ioliu.cn/v1/?url='

然后在axios請求里面拼接一下字符串

axios.get(API_PROXY + 'http://music.163.com/api/playlist/detail?id=19723756')

js 完整代碼如下

<script>
const API_PROXY = 'https://bird.ioliu.cn/v1/?url=' import axios from 'axios' export default { name: 'hello', data () { return { msg: 'vue調用網易雲接口', author: '泥猴啊', musics: [] } }, mounted: function () { axios.get(API_PROXY + 'http://music.163.com/api/playlist/detail?id=19723756') .then(function (res) { console.log(res) }, function (error) { console.log(error) }) } } </script>

打開瀏覽器console界面

Object {data: Object, status: 200, statusText: "OK", headers: Object, config: Object…}config:Objectdata: Objectheaders: Objectrequest: XMLHttpRequeststatus: 200statusText: "OK"__proto__: Object

請求成功

賦值給musics

this.musics = res.data.result.tracks

發現頁面有個報錯

Uncaught (in promise) TypeError: Cannot set property 'musics' of undefined

musics沒有定義
因為這里,this的指向不是當前的vue實例
那我們在使用axios之前重新,定義一下this

var _this = this

axios使用_this就好了

mounted部分代碼

  mounted: function () { var _this = this axios.get(API_PROXY + 'http://music.163.com/api/playlist/detail?id=19723756') .then(function (res) { _this.musics = res.data.result.tracks console.log(_this.musics) }, function (error) { console.log(error) }) }

再打開控制台,發現沒有報錯,請求的數據也是我們想要的
請求成功1

再次修改一下模板

我們再增加圖片數據

修改好的模板如下

<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>{{ author }}</h2> <ul v-for="music in musics"> <li> {{ music.name }} </li><br> <li> <img :src="music.album.picUrl" style="width:200px;"> </li> </ul> </div> </template>

完整代碼如下

<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>{{ author }}</h2> <ul v-for="music in musics"> <li> {{ music.name }} </li><br> <li> <img :src="music.album.picUrl" style="width:200px;"> </li> </ul> </div> </template> <script> const API_PROXY = 'https://bird.ioliu.cn/v1/?url=' import axios from 'axios' export default { name: 'hello', data () { return { msg: 'vue調用網易雲接口', author: '泥猴啊', musics: [] } }, mounted: function () { var _this = this axios.get(API_PROXY + 'http://music.163.com/api/playlist/detail?id=19723756') .then(function (res) { _this.musics = res.data.result.tracks console.log(_this.musics) }, function (error) { console.log(error) }) } } </script>

最后效果圖如下

最后效果圖
_

3.2 php用curl代理

這里演示vue-resource的寫法 + php curl 完成代理請求

前面我們安裝了vue-resource模塊,我們要在main.js加載一下vue-resource模塊

加載

import VueResource from 'vue-resource'

使用

Vue.use(VueResource)

為了避免和之前頁面混淆,我們重新新增一個curl頁面,路由同樣新增加一條'/curl'的路由

index.js 完整代碼如下

import Vue from 'vue' import Router from 'vue-router' import Hello from '@/components/Hello' import Curl from '@/components/Curl' import VueResource from 'vue-resource' Vue.use(Router) Vue.use(VueResource) export default new Router({ routes: [ { path: '/', name: 'Hello', component: Hello }, { path: '/curl', name: 'Curl', component: Curl } ] })

其實vue-resourceget方法基本上和axios很像,基本上沒有太多變動

  mounted: function () { this.$http.get('http://localhost/curl.php', {}, { headers: { }, emulateJSON: true }).then(function (res) { this.musics = res.data.result.tracks console.log(this.musics) }, function (error) { console.log(error) }) }

headers get方法里面不用填寫參數,如果是post方式發送請求
則要設置Access-Control-Allow-Origin: *

完整代碼如下 src\components\Curl.vue

<template> <div class="curl"> <h1>{{ msg }}</h1> <h2>{{ author }}</h2> <ul v-for="music in musics"> <li> {{ music.name }} </li><br> <li> <img :src="music.album.picUrl" style="width:200px;"> </li> </ul> </div> </template> <script> export default { name: 'curl', data () { return { msg: 'vue調用網易雲接口', author: '泥猴啊', musics: [] } }, mounted: function () { this.$http.get('http://localhost/curl.php', {}, { headers: { }, emulateJSON: true }).then(function (res) { this.musics = res.data.result.tracks console.log(this.musics) }, function (error) { console.log(error) }) } } </script>

當然了,最重要的是curl.php這個部分代碼怎么寫了
curl.php 完整代碼

<?php // header('Content-type:text/html;Charset=utf-8'); header('Content-Type:text/json;charset=utf-8');//設置返回文件的類型 header('Access-Control-Allow-Origin: *');//設置允許所有跨域 $id = '19723756'; //id $va_url = 'http://music.163.com/api/playlist/detail?'; //驗證的 url 鏈接地址 $post_fields = "id={$id}"; //post提交信息串 $curl = curl_init(); //初始化一個cURL會話,必有 //curl_setopt()函數用於設置 curl 的參數,其功能非常強大,具體看手冊 curl_setopt($curl, CURLOPT_URL, $va_url); //設置驗證登陸的 url 鏈接 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //設置結果保存在變量中,還是輸出,默認為0(輸出) curl_setopt($curl, CURLOPT_POST, 1); //模擬post提交 curl_setopt($curl, CURLOPT_POSTFIELDS, $post_fields); //設置post串 //避免https請求報錯 Curl error: SSL certificate problem: unable to get local issuer certificate curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($curl); //執行此cURL會話,必有 // echo "<pre>"; // print_r(json_decode($data)); echo $data; //檢查是否有錯誤 if(curl_errno($curl)) { exit('Curl error: ' . curl_error($curl)); } curl_close($curl); //關閉會話 

curl請求的話就解釋了,大家可以去看手冊
最重要的是設置頭文件允許跨域

header('Access-Control-Allow-Origin: *');

如果沒有設置這個的話,代理也是沒有意思的,不然前端還是會提示跨域

當然啦,你要把curl.php這個文件丟在你apache或者nginx根目錄,同時apache或者nginx服務器也別忘記啟用了哦。

請求成功2

3.3 nodejs代理

同樣的我們新建一個Node.vue的模板和/node的路由

    {
      path: '/node', name: 'Node', component: Node }

index.js 完整代碼

import Vue from 'vue' import Router from 'vue-router' import Hello from '@/components/Hello' import Curl from '@/components/Curl' import Node from '@/components/Node' import VueResource from 'vue-resource' Vue.use(Router) Vue.use(VueResource) export default new Router({ routes: [ { path: '/', name: 'Hello', component: Hello }, { path: '/curl', name: 'Curl', component: Curl }, { path: '/node', name: 'Node', component: Node } ] })

設置代理

打開config/index.js
修改proxyTable: {}部分
修改為

    proxyTable: {
      '/api': { target: 'http://music.163.com/api', changeOrigin: true, pathRewrite: { '^/api': '' } } }

第一行的'/api'指的是虛擬路徑
target指的是目標地址,也就是實際api的地址
pathRewrite規則重寫

然后在代碼頁面修改一下請求地址

  mounted: function () { this.$http.get('/api/playlist/detail?id=19723756', {}, { headers: { }, emulateJSON: true }).then(function (res) { this.musics = res.data.result.tracks console.log(this.musics) }, function (error) { console.log(error) }) }

/api/playlist/detail?id=19723756上面的這個地址其實就等於http://localhost:8080/api+/playlist/detail?id=19723756

注意這里一定要重啟一下node,因為你修改了node的配置一定要重啟才能生效

在命令符窗口ctrl + c
然后重新執行cnpm run dev
這時候,命令窗口會提示

[HPM] Proxy created: /api -> http://music.163.com/api [HPM] Proxy rewrite rule created: "^/api" ~> "" > Starting dev server...

說明代理成功

代理成功

然后訪問http://localhost:8080/#/node

請求成功3

就能看到效果了
完整代碼 src\components\Node.vue

<template> <div class="curl"> <h1>{{ msg }}</h1> <h2>{{ author }}</h2> <ul v-for="music in musics"> <li> {{ music.name }} </li><br> <li> <img :src="music.album.picUrl" style="width:200px;"> </li> </ul> </div> </template>
<script>
export default { name: 'curl', data () { return { msg: 'vue調用網易雲接口', author: '泥猴啊', musics: [] } }, mounted: function () { this.$http.get('/api/playlist/detail?id=19723756', {}, { headers: { }, emulateJSON: true }).then(function (res) { this.musics = res.data.result.tracks console.log(this.musics) }, function (error) { console.log(error) }) } } </script>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM