從零開始學 Web 之 Vue.js(四)Vue的Ajax請求和跨域
大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新......
- github:https://github.com/Daotin/Web
- 微信公眾號:Web前端之巔
- 博客園:http://www.cnblogs.com/lvonve/
- CSDN:https://blog.csdn.net/lvonve/
在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的項目。現在就讓我們一起進入 Web 前端學習的冒險之旅吧!
一、Vue發送Ajax請求
之前我們發送Ajax請求的方式,一是原生的方式發送,二是通過jQuery來發送Ajax請求。
但是我們知道,在Vue裏面是不推薦使用jQuery的,那麽如何使用Vue來發送Ajax請求呢?
在Vue中可以使用第三方插件vue-resource
來實現Ajax請求的發送。
1、vue-resource 安裝
1、通過npm的方式在線安裝:npm install vue-resource
2、在 github 中下載 vue-resource 的 文件 (在 dist 文件夾下有個 vue-resource.js 文件。)
3、使用 CDN。<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
2、vue-resource 使用
參考鏈接:https://github.com/pagekit/vue-resource/blob/develop/docs/http.md
步驟:
1、在Vue.js之後引入vue-resource.js文件(因為vue-resource.js文件是依賴於Vue的)
2、全局使用:
then後面第一個參數是請求成功的回調函數;第二個參數是請求失敗的回調函數。
獲取到的結果在回調函數的參數中。
Vue.http.get('/someUrl', [config]).then(successCallback, errorCallback); Vue.http.post('/someUrl', [body], [config]).then(successCallback, errorCallback); Vue.http.jsonp('/someUrl', [config]).then(successCallback, errorCallback);
3、局部使用:在methods的事件中,使用 this.$http.get/post/jsonp();
的形式發起請求。
this.$http.get('/someUrl', [config]).then(successCallback, errorCallback);
this.$http.post('/someUrl', [body], [config]).then(successCallback, errorCallback);
this.$http.jsonp('/someUrl', [config]).then(successCallback, errorCallback);
示例:通過三個按鈕點擊分別獲取get,post,jsonp請求。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<script src="./lib/vue-resource-1.3.4.js"></script>
</head>
<body>
<div id="box">
<input type="button" value="get請求" @click="getClick">
<input type="button" value="post請求" @click="postClick">
<input type="button" value="jsonp請求" @click="jsonpClick">
</div>
<script>
var vm = new Vue({
el: " #box ",
data: {},
methods: {
getClick() {
// 參數1:測試用的地址:http://vue.studyit.io/api/getlunbo
// 參數2:[config] 可選
this.$http.get("http://vue.studyit.io/api/getlunbo").then(result => {
console.log("ok");
console.log(result.body);
});
},
postClick() {
// 參數1:測試用的地址:http://vue.studyit.io/api/getlunbo
// 參數2:[data]數據,可為Object,FormData,String,這裏為空
// 參數3:[config] 可選,但是emulateJSON = "true" 表名表單格式為:application/x-www-form-urlencoded,否則
// 可能有的瀏覽器不認識。
this.$http.post("http://vue.studyit.io/api/post", "", {
emulateJSON: true
}).then(result => {
console.log(result.body);
});
},
jsonpClick() {
this.$http.jsonp("http://vue.studyit.io/api/getlunbo").then(result => {
console.log(result.body);
});
}
}
});
</script>
</body>
</html>
註意:獲取到的數據在成功回調函數參數data的中,data是個對象,具體需要的數據是 data.body。
二、vue-resource 跨域請求數據
1、jsonp的實現原理
jsonp主要是為了解決跨域請求問題的。
我們知道,由於瀏覽器的安全性限制,不允許AJAX訪問 協議不同、域名不同、端口號不同的數據接口,瀏覽器認為這種訪問不安全。
但是,script標簽src屬性中的鏈接卻可以訪問跨域的js腳本,於是利用這種特性,我們讓服務器不再返回數據,而是返回一段調用某個函數的js代碼,然後在script中進行調用,就實現了跨域。
示例:使用JSONP,添加了一個script標簽,標簽的src指向了另一個域 www.xxx.com下的 jsonp.js 腳本。
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
<script type="text/javascript">
function jsonphandle(data){
alert("age:" + data.age + "name:" + data.name);
}
</script>
<script type="text/javascript" src="jquery-1.8.3.min.js">
</script>
<script type="text/javascript" src="http://www.xxx.com/jsopn.js"></script>
</body>
</html>
要實現跨域,所以返回的 js 代碼應該是一個函數的調用。www.xxx.com 下的 jsonp.js 代碼如下:
jsonphandle({
"age" : 15,
"name": "John",
})
於是,結果就彈出對話框。
我們再改進一下,在script的src中傳入的大多是後臺文件,這裏以php文件為例。
由於我們之前傳入 js 文件只是想得到一個函數的調用而已,那麽傳入php文件怎麽獲取函數的調用呢?
<!DOCTYPE html>
<html>
<head>
<title>GoJSONP</title>
</head>
<body>
<script type="text/javascript">
function jsonphandle(data){
alert("age:" + data.age + "name:" + data.name);
}
</script>
<script type="text/javascript" src="jquery-1.8.3.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
var url = "http://www.xxx.com/jsonp.php?id=1&callback=jsonphandle";
var obj = $('<script><\/script>');
obj.attr("src",url);
$("body").append(obj);
});
</script>
</body>
</html>
這裏動態的添加了一個script標簽,src指向跨域的一個php腳本,並且將上面的js函數名作為callback參數傳入,那麽我們看下PHP代碼怎麽寫的:
<?php
$data = array(
'age' => 20,
'name' => '張三',
);
$callback = $_GET['callback'];
echo $callback."(".json_encode($data).")";
return;
php代碼返回的也是一個函數調用,我們需要的數據,就在其參數裏面。成功彈出提示框:
jsonphandle({
"age" : 15,
"name": "張三",
})
最後,jQuery提供了方便使用jsonp的方式:
<!DOCTYPE html>
<html>
<head>
<title>GoJSONP</title>
</head>
<body>
<script type="text/javascript" src="jquery-1.8.3.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
type : "get",
async: false,
url : "http://www.xxx.com/jsonp.php?id=1",
dataType: "jsonp",
jsonp:"callback", //請求php的參數名
jsonpCallback: "jsonhandle",//要執行的回調函數
success : function(data) {
alert("age:" + data.age + "name:" + data.name);
}
});
});
</script>
</body>
</html>
其中參數 data,即為php代碼返回的函數調用的參數,就是我們先要的數據。
參考鏈接:https://blog.csdn.net/u011897301/article/details/52679486
2、跨域獲取電影信息
這裏我使用 聚合數據:https://www.juhe.cn 的免費API。
使用方式很簡單,註冊之後,申請數據後,在個人中心->我的數據,接口名稱上方查看key值。
而我們訪問的url即為:http://v.juhe.cn/movie/index?key=您申請的key&title=頭文字D
我們在name輸入框中輸入電影名稱後,點擊查詢按鈕即可顯示相關信息。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<script src="./lib/vue-resource-1.3.4.js"></script>
<style>
* {
padding: 0;
margin: 0;
position: relative;
}
/* 實現任意無寬高盒子居中 */
#app {
width: 100%;
position: absolute;
left: 50%;
/* top: 100px; */
transform: translateX(-50%);
}
.box {
width: 100%;
height: 40px;
background-color: #ccc;
display: inline-block;
text-align: center;
line-height: 40px;
border: 1px solid #aaa;
box-sizing: border-box;
border-bottom: none;
}
.box>input[type="button"] {
width: 60px;
background-color: #aaa;
border: 0;
border: 1px solid #aaa;
margin: 0 20px;
}
.tb {
width: 100%;
height: 100%;
text-align: center;
border-collapse: collapse;
border-color: #ccc;
}
.th {
background-color: rgb(24, 204, 204);
}
</style>
</head>
<body>
<div id="app">
<div class="box">
<label for="name">
電影名:
<input type="text" id="name" v-model="name">
</label>
<input type="button" value="查詢" @click="addClick">
</div>
<table border="1" cellspacing="0" class="tb">
<thead class="th">
<tr>
<th>年份</th>
<th>標題</th>
<th>評分</th>
<th>類型</th>
<th>時長</th>
<th>主演</th>
<th>簡介</th>
<th>刪除</th>
</tr>
</thead>
<!-- 有查詢的話,這裏就不應該固定死,而是根據keywords動態生成新的數組 -->
<!-- <tr v-for="item in list"></tr> -->
<tbody>
<tr v-for="item in list">
<td>{{item.year}}</td>
<td>《{{item.title}}》</td>
<td>{{item.rating}}</td>
<td>{{item.genres}}</td>
<td>{{item.runtime}}</td>
<td>{{item.actors}}</td>
<td>{{item.plot_simple}}</td>
<td>
<!-- 綁定的事件是可以傳參數的,這裏傳入需要刪除的對象id -->
<a href="javascript:;" @click.prevent="delClick(item.id)">del</a>
</td>
</tr>
</tbody>
</table>
</div>
<script>
// 全局配置數據接口的根域名
//Vue.http.options.root = 'http://v.juhe.cn/';
var vm = new Vue({
el: "#app",
data: {
name: "",
rating: "",
genres: "",
runtime: "",
title: "",
actors: "",
plot_simple: "",
year: "",
// 假數據
list: [{
'rating': 7.3,
'genres': '動作/驚悚/科幻',
'runtime': '139分鐘',
"title": "哥斯拉",
"actors": "馬修·布羅德裏克",
"plot_simple": "一道亮光劃過天際,太平洋上波濤洶湧",
"year": "1998",
},
{
'rating': 1,
'genres': 2,
'runtime': 3,
"title": 4,
"actors": 5,
"plot_simple": 6,
"year": 7,
}
]
},
methods: {
// 按鈕點擊事件處理函數
addClick() {
this.getAllList(this.name);
this.name = "";
},
// 獲取電影信息
getAllList(title) {
// console.log(2);
title = this.name;
this.$http.get(`http://v.juhe.cn/movie/index?key=a6c9eddf926517774fe9aa1106ce9295&title=${title}`).then(
result => {
if (result.body.result.length == 0) {
alert("無此電影信息");
return;
}
this.list = result.body.result;
});
}
}
});
</script>
</body>
</html>
由於API要求我們訪問的方式為 get請求,所以我們使用 this.$http.get
的方式來獲取電影信息。
然後打印獲取到的數據result,但是卻爆出如下錯誤信息:
錯誤信息是表示,無法實現跨域。而我們之前知道 jsonp是可以實現跨域問題的。
於是我將get請求改為jsonp請求:this.$http.jsonp
就可以了。
改進:
之前直接把數據接口放在了請求地址裏面,如果地址變了,就要在請求地址裏面修改,如果不止一個還有其他post,get請求等,那麽就要修改多次,所以我們有必要動態的指定數據接口。
使用:Vue.http.options.root = ‘http://v.juhe.cn/‘;
來指定數據接口的根地址。
我們在請求的時候只需要寫 movie/index?key=a6c9eddf926517774fe9aa1106ce9295&title=${title}
就可以了。
註意:後續地址,不要寫 / ,否則就不會將根地址和後續地址進行拼接。
當然,對於我們發給服務器的數據,可能會需要 emulateJSON = true;
我們也可以進行全局配置:Vue.http.options.emulateJSON = true;
從零開始學 Web 之 Vue.js(四)Vue的Ajax請求和跨域