第2章:使用axios/vue-resource发送HTTP请求
一,发送AJAX请求
1.简介
vue本身不支持发送AJAX请求,需要使用vueresource、axios等插件实现
axios是一个基于Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对vueresource进行更新和维护
参考:GitHub上搜索axios,查看API文档
2.使用axios发送AJAX请求
2.1安装axios并引入
使用cnpm可以下载,下载到当前目录的node_modules/axios/dist下
cnpm install axios -Y
直接下载引入也可以
2.2基本用法
axios([options])
axios.get(url[,options]);
传参方式:
1.通过url传参
2.通过params选项传参
axios.post(url,data,[options]);
示例day02/01.html
先请求一个文本,看一下相应
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>发送AJAX请求</title> <script src="js/vue.js"></script> <script src="js/axios.min.js"></script> <script> window.onload=function(){ new Vue({ el: '#itany', methods:{ send(){ axios({ method:'get', // 方法是get url: 'user.json' // url为当前文件夹下的一个json文件 }).then(function(resp){ // 请求完成成功后返回Proise对象,使用then调用这个对象 catch是请求失败调用 console.log(resp); }) } } }); } </script> </head> <body> <div id="itany"> <button @click="send">发送AJAX请求</button> </div> </body> </html>
页面显示
注意:需要使用web服务器访问,不能直接打开文件,如果直接打开html文件会提示错误
requests are only supported for protocol schemes
意思在支持的框架是http,data等,不支持file
本次我们在本机搭建了IIS服务器,在Linux上搭建Nginx也可以
resp相应包含很多信息如数据请求头相应状态码等,也可以直接打印json数据data
console.log(resp.data);
请求失败也会返回相应,增加失败的输出,需要修改设置一个不存在的文件即可观察到请求失败的输出
send(){ axios({ method:'get', // 方法是get url: 'user.jsonaaa' // url为当前文件夹下的一个json文件 }).then(function(resp){ // 请求完成成功后返回Proise对象,使用then调用这个对象 catch是请求失败调用 console.log(resp.data); }).catch(resp => { console.log('请求失败:'+resp.status+','+resp.statusText) }) }
输出如下
通过url传递参数示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>发送AJAX请求</title> <script src="js/vue.js"></script> <script src="js/axios.min.js"></script> <script> window.onload=function(){ new Vue({ el: '#itany', methods:{ send(){ axios({ method:'get', // 方法是get url: 'user.json' // url为当前文件夹下的一个json文件 }).then(function(resp){ // 请求完成成功后返回Proise对象,使用then调用这个对象 catch是请求失败调用 console.log(resp.data); }).catch(resp => { console.log('请求失败:'+resp.status+','+resp.statusText) }) }, sendGet(){ axios.get('server.php?name=tom&age=23') .then(resp =>{ console.log(resp); }).catch(err =>{ console.log('请求失败:'+err.status+' '+err.statusText); }); } } }); } </script> </head> <body> <div id="itany"> <button @click="send">发送AJAX请求</button> <button @click="sendGet">GET方式发送AJAX请求</button> </div> </body> </html>
解析
通过url往页面server.php传递键值对参数
axios.get('server.php?name=tom&age=23')
注意:访问需要配置好php环境 搭建方法参考:https://www.cnblogs.com/minseo/p/8821948.html
server.php
<?php //获取参数 $name=$_GET['name']; $age=$_GET['age']; //响应数据 echo '姓名:',$name,',年龄:',$age; ?>
页面显示
拼接方式如果键值对太多比较麻烦,可以通过params选项传参
axios.get('server.php',{ params:{ name: 'alict', age: 18 } })
以上为get请求发送方式,下面演示post请求
axios.post(url,data,[options]);
代码增加一个post方法
sendPost(){ axios.post('server.php',{ params:{ name:'alice', age:19 } }) .then(resp =>{ console.log(resp.data); }).catch(err =>{ console.log('请求失败:'+err.status+' '+err.statusText); }); }
html代码
<button @click="sendPost">POST方式发送AJAX请求</button>
同时server.php也要修改GET方法为POST方法
页面显示
但是这里可以看到post发送的值,是一个json对象,不是以表单的形式发送
axios的post发送请求有缺陷
axios默认发送数据时,数据格式是Reques Payload,并非我们常用的表单Form Data格式,所以参数必须以键值对的形式传递,不能以json的方式传参
1,自己拼接键值对
修改代码,改成拼接模式
sendPost(){ // axios.post('server.php',{ // params:{ // name:'alice', // age:19 // } // }) axios.post('server.php','name=alice&age=20') .then(resp =>{ console.log(resp.data); }).catch(err =>{ console.log('请求失败:'+err.status+' '+err.statusText); }); }
页面显示
自己拼接比较麻烦,使用转换数据的方法
2,使用transformRequest
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>发送AJAX请求</title> <script src="js/vue.js"></script> <script src="js/axios.min.js"></script> <script> window.onload=function(){ new Vue({ el: '#itany', methods:{ send(){ axios({ method:'get', // 方法是get url: 'user.json' // url为当前文件夹下的一个json文件 }).then(function(resp){ // 请求完成成功后返回Proise对象,使用then调用这个对象 catch是请求失败调用 console.log(resp.data); }).catch(resp => { console.log('请求失败:'+resp.status+','+resp.statusText) }) }, sendGet(){ // axios.get('server.php?name=tom&age=23') axios.get('server.php',{ params:{ name: 'alict', age: 18 } }) .then(resp =>{ console.log(resp); }).catch(err =>{ console.log('请求失败:'+err.status+' '+err.statusText); }); }, sendPost(){ axios.post('server.php',{ params:{ name:'alice', age:19 } }) .then(resp =>{ console.log(resp.data); }).catch(err =>{ console.log('请求失败:'+err.status+' '+err.statusText); }); } } }); } </script> </head> <body> <div id="itany"> <button @click="send">发送AJAX请求</button> <button @click="sendGet">GET方式发送AJAX请求</button> <button @click="sendPost">POST方式发送AJAX请求</button> </div> </body> </html>
3,如果使用模块化开发,可以使用qs模块进行转换
练习:使用获取指定GitHub账户信息并显示01.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>发送AJAX请求</title> <script src="js/vue.js"></script> <script src="js/axios.min.js"></script> <script> window.onload=function(){ new Vue({ el: '#itany', data: { user:'', uid:'' }, methods:{ send(){ axios({ method:'get', // 方法是get url: 'user.json' // url为当前文件夹下的一个json文件 }).then(function(resp){ // 请求完成成功后返回Proise对象,使用then调用这个对象 catch是请求失败调用 console.log(resp.data); }).catch(resp => { console.log('请求失败:'+resp.status+','+resp.statusText) }) }, sendGet(){ // axios.get('server.php?name=tom&age=23') axios.get('server.php',{ params:{ name: 'alict', age: 18 } }) .then(resp =>{ console.log(resp); }).catch(err =>{ console.log('请求失败:'+err.status+' '+err.statusText); }); }, sendPost(){ // 方式1无法传递 // axios.post('server.php',{ // params:{ // name:'alice', // age:19 // } // }) // 方式2自己拼接 // axios.post('server.php','name=alice&age=20') // 方式3转换 axios.post('server.php',this.user,{ transformRequest:[ function(data){ let params=''; for(let index in data){ params+=index+'='+data[index]+'&'; } return params; } ] }) .then(resp =>{ console.log(resp.data); }).catch(err =>{ console.log('请求失败:'+err.status+' '+err.statusText); }); }, getUserById(uid){ axios.get(`https://api.github.com/users/${uid}`) .then(resp =>{ console.log(resp.data); this.user=resp.data; }) }, } }); } </script> </head> <body> <div id="itany"> <button @click="send">发送AJAX请求</button> <button @click="sendGet">GET方式发送AJAX请求</button> <button @click="sendPost">POST方式发送AJAX请求</button> <hr> <br> GitHub ID: <input type="text" v-model="uid"> <button @click="getUserById(uid)">获取指定GitHub账户信息并显示</button> <br> 姓名:{{user.login}} <br> 头像:<img :src="user.avatar_url" alt=""> <hr> </div> </body> </html>
githup的用户api是公开的,可以通过用户的id进行获取
页面显示
注意:这里双向数据绑定要绑定uid,我觉得应该绑定user,不清楚为什么
3.使用vue-resource发送跨域请求
下载
cnpm install vue-resource@1.3.4 -S
引入
<script src="js/vue-resource.min.js"></script>
示例在360搜索里面搜索a
在01.html中增加以下代码
html中
<button @click="sendJSONP">发送JSONP请求</button>
<scripts>中
sendJSONP(){ // https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&src=so_home&fields=word&word=a this.$http.jsonp('https://sug.so.360.cn/suggest',{ params:{ word:'a' } }).then(resp => { console.log(resp.data.result) }); },
参数是url以及需要搜索的a
返回和axios请求一样promise对象,使用resp.data.result输出,之前的result参数可能是s
页面显示
向百度发送JSONP请求
修改代码如下
html
<button @click="sendJSONP2">向百度发送JSONP请求</button>
<scripts>
sendJSONP2(){ //https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=a&json=1&p=3&sid=1420_21118_17001_21931_23632_22072&req=2&csor=1&cb=jQuery110208075694879886905_1498805938134&_=1498805938138 this.$http.jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',{ params:{ wd:'a' }, jsonp:'cb' }).then(resp => { console.log(resp.data.s) }); },
注意:百度使用的是wd,360使用的是word,//百度使用的jsonp参数名为cb,所以需要修改
使用this.$http发送请求 this.$http.get(url, [options]) this.$http.head(url, [options]) this.$http.delete(url, [options]) this.$http.jsonp(url, [options]) this.$http.post(url, [body], [options]) this.$http.put(url, [body], [options]) this.$http.patch(url, [body], [options])
4.练习
百度搜索列表
百度搜索输入一个关键字会列出联想的一些关键字下面在输入框输入搜索关键字显示
02.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>发送AJAX请求</title> <style> .current{ background-color:#ccc; } </style> <script src="js/vue.js"></script> <script src="js/vue-resource.min.js"></script> <script> window.onload=function(){ new Vue({ el:'#itany', data:{ keyword:'', myData:[], now:-1 //当前选中项的索引 }, methods:{ getData(e){ //如果按方向键上、下,则不发请求 if(e.keyCode==38||e.keyCode==40) return; this.$http.jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',{ params:{ wd:this.keyword }, jsonp:'cb' }).then(resp => { this.myData=resp.data.s; }); }, changeDown(){ this.now++; this.keyword=this.myData[this.now]; if(this.now==this.myData.length){ this.now=-1; } }, changeUp(){ this.now--; this.keyword=this.myData[this.now]; if(this.now==-2){ this.now=this.myData.length-1; } } } }); } </script> </head> <body> <div id="itany"> <input type="text" v-model="keyword" @keyup="getData($event)" @keydown.down="changeDown" @keydown.up.prevent="changeUp"> <ul> <li v-for="(value,index) in myData" :class="{current:index==now}"> {{value}} </li> </ul> <p v-show="myData.length==0">暂无数据....</p> </div> </body> </html>
页面显示