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)
})
}

再打开控制台,发现没有报错,请求的数据也是我们想要的

再次修改一下模板

我们再增加图片数据

修改好的模板如下

<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服务器也别忘记启用了哦。

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

就能看到效果了
完整代码 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>

vue中的跨域问题的更多相关文章

  1. vue中解决跨域问题

    方法1.后台更改header header('Access-Control-Allow-Origin:*');//允许所有来源访问 header('Access-Control-Allow-Metho ...

  2. Vue 中 axios 跨域配置 (!!!配置完成需要重新运行,不然也不起作用)

    当拿到一个网址如:https://music.163.com/store/api/categorypage/list  获取数据是出现如下: 证明该网址不能非常直观的拿到数据.接下来我们试试跨域拿这个 ...

  3. vue中的跨域

    proxyTable: { '/zabbix_api': { target: 'http://10.88.22.8',//设置你调用的接口域名和端口号 别忘了加http changeOrigin: t ...

  4. 前端vue开发中的跨域问题解决,以及nginx上线部署。(vue devServer与nginx)

    前言 最近做的一个项目中使用了vue+springboot的前后端分离模式 在前端开发的的时候,使用vue cli3的devServer来解决跨域问题 上线部署则是用的nginx反向代理至后台服务所开 ...

  5. Vue用axios跨域访问数据

    Vue用axios跨域访问数据axios是vue-resource的替代品,vue-resource不再维护.安装axios:npm install axios使用vue-cli开发时,由于项目本身启 ...

  6. Vue开发环境跨域访问

    Vue开发环境跨域访问其他服务器或者本机其他端口,需要配置项目中config/index.js文件,修改如下 module.exports = { dev: { // Paths assetsSubD ...

  7. 搞懂:前端跨域问题JS解决跨域问题VUE代理解决跨域问题原理

    什么是跨域 跨域:一个域下的文档或脚本试图去请求另一个域下的资源 广义的跨域包含一下内容: 1.资源跳转(链接跳转,重定向跳转,表单提交) 2.资源请求(内部的引用,脚本script,图片img,fr ...

  8. js中各种跨域问题实战小结(二)

    这里接上篇:js中各种跨域问题实战小结(一) 后面继续学习的过程中,对上面第一篇有稍作休整.下面继续第二部分: -->5.利用iframe和location.hash -->6.windo ...

  9. js中各种跨域问题实战小结(一)

    什么是跨域?为什么要实现跨域呢? 这是因为JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.也就是说只能访问同一个域中的资源.我觉得这就有必要了解下javascript中的同源策略 ...

随机推荐

  1. 磁盘性能评价指标—IOPS和吞吐量

    转:http://blog.csdn.net/hanchengxi/article/details/19089589 一.磁盘 I/O 的概念 I/O 的概念,从字义来理解就是输入输出.操作系统从上层 ...

  2. 【转】Android动态破解微信本地数据库(EnMicroMsg.db)

    最近在公司接了一个任务,需要在几百台手机上安装一个app,目的是获取微信里面的通讯录,并且定时的把他发送到我们的服务器上.当时依次尝试的如下几个方案: 1.通过群控,将好友截图发送到服务端(pytho ...

  3. 004_Python高级特性(1):Iterators、Generators和itertools(参考)

    对数学家来说,Python这门语言有着很多吸引他们的地方.举几个例子:对于tuple.lists以及sets等容器的支持,使用与传统数学类 似的符号标记方式,还有列表推导式这样与数学中集合推导式和集的 ...

  4. String,StringBuffer,StringBuilder的区别与共同点

    1. String与StringBuffer,StringBuilder的区别: String为什么不可变:String存储数据是有final修饰的字符数组private final char val ...

  5. 初学Python——线程

    什么是线程? 线程是进程内的独立的运行线路,是操作系统能够进行运算调度的最小单位,同时也是处理器调度的最小单位.线程被包含在进程之内,是进程中实际运作单位. 一个线程指的是进程中的一个单一顺序的控制流 ...

  6. 输出 1-100 内的奇数和偶数,并对其分别求和(while嵌套if-else循环)

    package com.summer.cn; /** * @author Summer * 输出 1-100 内的奇数和偶数,并对其分别求和 * while嵌套if-else循环 */ public ...

  7. redis学习(六)——Sorted Set数据类型

    一.概述: Sorted Set(有序集合)和Set类型极为相似,它们都是字符串的集合,都不允许重复的成员出现在一个Set中.它们之间的主要差别是Sorted Set中的每一个成员都会有一个分数(sc ...

  8. BZOJ1063 NOI2008 道路设计 树形DP

    题目传送门: BZOJ 题意精简版:给出一棵树,在一种方案中可以将树的若干链上的所有边的边权改为$0$,但需要保证任意两条链之间没有交点.问最少的一种方案,使得从根节点到其他节点经过的边的边权和的最大 ...

  9. Codeforces Round #545 (Div. 1) Solution

    人生第一场Div. 1 结果因为想D想太久不晓得Floyd判环法.C不会拆点.E想了个奇奇怪怪的set+堆+一堆乱七八糟的标记的贼难写的做法滚粗了qwq靠手速上分qwqqq A. Skyscraper ...

  10. Android Studio 2.2新增布局——ConstraintLayout完全解析

    ,但是Button并没有紧贴到布局的最右侧,这是为什么呢?实际上,Android Studio给控件的每个方向上的约束都默认添加了一个16dp的间距,从Inspector上面也可以明显地看出来这些间距 ...