vue.js默認沒有提供ajax功能的。javascript
因此使用vue的時候,通常都會使用axios的插件來實現ajax與後端服務器的數據交互。html
注意,axios本質上就是javascript的ajax封裝,因此會被同源策略限制。前端
下載地址:vue
https://unpkg.com/axios@0.18.0/dist/axios.js
https://unpkg.com/axios@0.18.0/dist/axios.min.js
使用文檔:https://www.kancloud.cn/yunye/axios/234845java
axios提供發送http請求的經常使用方法有兩個:axios.get() 和 axios.post() 。python
jquery
刪 deleteios
改 put/patchweb
查 getajax
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="vue.js"></script> <script src="axios.js"></script> </head> <body> <div id="app"></div> <script> var vm = new Vue({ el:"#app", data:{}, // 在初始化的時候自動發送ajax獲取數據 created(){ axios.get("http://wthrcdn.etouch.cn/weather_mini?city=北京") .then(response=>{ console.log("http請求成功") console.log(response); // http響應對象 console.log(response.data); // 返回的數據 }) .catch(error=>{ // 請求失敗或者then裏面代碼出現錯誤時 console.log("http請求失敗或者then裏面代碼報錯"); console.log(error); console.log(error.response.data); // 若是但願獲取來自服務器的錯誤信息 }); } }); </script> </body> </html>
// 發送get請求 // 參數1: 必填,字符串,請求的數據接口的url地址,例如請求地址:http://www.baidu.com?id=200 // 參數2:可選,請求參數和請求頭內容,json對象,要提供給數據接口的參數 axios.get('服務器的資源地址',{ // http://www.baidu.com params:{ 參數名:'參數值', // id: 200, }, headers:{ 選項名:'選項值', // 請求頭 } }).then(response=>{ // 請求成功之後的回調函數 console.log("請求成功"); console.log(response.data); // 獲取服務端提供的數據 }).catch(error=>{ // 請求失敗之後的回調函數 console.log("請求失敗"); console.log(error.response); // 獲取錯誤信息 }); // 發送post請求,參數和使用和axios.get()相似。 // 參數1: 必填,字符串,請求的數據接口的url地址 // 參數2:必填,json對象,要提供給數據接口的參數,若是沒有參數,則必須使用{} // 參數3:可選,json對象,請求頭信息 axios.post('服務器的資源地址',{ username: 'xiaoming', password: '123456' },{ headers:{ 選項名:"選項值", } }) .then(response=>{ // 請求成功之後的回調函數 console.log(response); }) .catch(error=>{ // 請求失敗之後的回調函數 console.log(error); }); // b'firstName=Fred&lastName=Flintstone'
注意:
axios.delete() 的用法和參數與axios.get()同樣,
axios.put()或者axios.patch的用法和參數與axios.post()同樣。
在http協議中,不一樣的請求動做都有不一樣的含義,例如:
get 表明向目標服務器請求獲取數據
post 表明向目標服務器請求上傳數據
put 表明向目標服務器請求更新數據【修改所有數據】
patch 表明向目標服務器請求更新數據【修改部分數據】
patch 表明向目標服務器請求更新數據
delete 表明向目標服務器請求刪除數據
json是 JavaScript Object Notation 的首字母縮寫,單詞的意思是javascript對象表示法,這裏說的json指的是相似於javascript對象的一種數據格式。
json的做用:在不一樣的系統平臺,或不一樣編程語言之間傳遞數據。
json數據對象相似於JavaScript中的對象,可是它的鍵對應的值裏面是沒有函數方法的,值能夠是普通變量,不支持undefined,值還能夠是數組或者json對象。
// 原生的js的json對象
var obj = {
age:10,
sex: '女',
work(){ // work: function(){}的簡寫
return "好好學習",
},
}
// json數據的對象格式,json數據格式,是沒有方法的,只有屬性,屬性值:字符串,數值(整數,浮點數,布爾值), json,
{
"name":"tom",
"age":18
}
// json數據的數組格式:
["tom",18,"programmer"]
複雜的json格式數據能夠包含對象和數組的寫法。
{
"name":"小明",
"age":200,
"is_delete": false,
"fav":["code","eat","swim","read"],
"son":{
"name":"小小明",
"age":100,
"lve":["code","eat"]
}
}
// 數組結構也能夠做爲json傳輸數據。
json數據能夠保存在.json文件中,通常裏面就只有一個json對象。
總結:
1. json文件的後綴是.json
2. json文件通常保存一個單一的json數據
3. json數據的屬性不能是方法或者undefined,屬性值只能:數值[整數,小數,布爾值]、字符串、json和數組
4. json數據只使用雙引號、每個屬性成員之間使用逗號隔開,而且最後一個成員沒有逗號。
{
"name":"小明",
"age":200,
"fav":["code","eat","swim","read"],
"son":{
"name":"小小明",
"age":100
}
}
工具:postman能夠用於測試開發的數據接口。
postman就是一個軟件,專門提供給開發者組織和測試http請求的。
方法 | 參數 | 返回值 | 描述 |
---|---|---|---|
stringify | json對象 | 字符串 | json對象轉成字符串 |
parse | 字符串 | json對象 | 字符串格式的json數據轉成json對象 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> // json語法 let humen = { "username":"xiaohui", "password":"1234567", "age":20 }; console.log(humen); console.log(typeof humen); // JSON對象提供對json格式數據的轉換功能 // stringify(json對象) # 用於把json轉換成字符串 let result = JSON.stringify(humen); console.log(result); console.log(typeof result); // parse(字符串類型的json數據) # 用於把字符串轉成json對象 let json_str = '{"password":"1123","age":20,"name":"xiaobai"}'; console.log(json_str) console.log(typeof json_str) let json_obj = JSON.parse(json_str); console.log(json_obj); console.log(typeof json_obj) console.log(json_obj.age) </script> </body> </html>
ajax,通常中文稱之爲:"阿賈克斯",是英文 「Async Javascript And Xml」的簡寫,譯做:異步js和xml數據傳輸數據。
ajax的做用: ajax可讓js代替瀏覽器向後端程序發送http請求,與後端通訊,在用戶不知道的狀況下操做數據和信息,從而實現頁面局部刷新數據/無刷新更新數據。
因此web開發中ajax是很經常使用的技術,主要用於操做後端提供的數據接口
,從而實現網站的先後端分離
。
ajax技術的原理是實例化js的XMLHttpRequest對象,使用此對象提供的內置方法就能夠與後端進行數據通訊。
實際而言,axios或者jQuery提供的ajax,本質上就是XMLHttpRequest對象操做的封裝。
數據接口,也叫api接口,表示後端提供
操做數據/功能的url地址給客戶端使用。
客戶端經過發起請求向服務端提供的url地址申請操做數據【操做通常:增刪查改】
同時在工做中,大部分數據接口都不是手寫,而是經過函數庫/框架來生成。
ajax的使用必須與服務端程序配合使用,可是目前咱們先學習ajax的使用,因此暫時先不涉及到服務端python代碼的編寫。所以,咱們可使用別人寫好的數據接口進行調用。
編寫代碼獲取接口提供的數據:
jQ版本
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/jquery-1.12.4.js"></script> <script> $(function(){ $("#btn").on("click",function(){ $.ajax({ // 後端程序的url地址 url: 'http://wthrcdn.etouch.cn/weather_mini', // 也可使用method,提交數據的方式,默認是'GET',經常使用的還有'POST' type: 'get', dataType: 'json', // 返回的數據格式,經常使用的有是'json','html',"jsonp" data:{ // 設置發送給服務器的數據,若是是get請求,也能夠寫在url地址的?後面 "city":'北京' } }) .done(function(resp) { // 請求成功之後的操做 console.log(resp); }) .fail(function(error) { // 請求失敗之後的操做 console.log(error); }); }); }) </script> </head> <body> <button id="btn">點擊獲取數據</button> </body> </html>
Vue版本
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> <script src="js/axios.js"></script> </head> <body> <div id="app"> <input type="text" v-model="city"> <button @click="get_weather">點擊獲取天氣</button> </div> <script> let vm = new Vue({ el:"#app", data:{ city:"", }, methods:{ get_weather(){ // http://wthrcdn.etouch.cn/weather_mini?city=城市名稱 axios.get("http://wthrcdn.etouch.cn/weather_mini?city="+this.city) .then(response=>{ console.log(response); }).catch(error=>{ console.log(error.response) }); // 上面的參數寫法,也能夠是下面這種格式: // axios.get("http://wthrcdn.etouch.cn/weather_mini",{ // // get請求的附帶參數 // params:{ // "city":"廣州", // } // }).then(response=>{ // console.log(response.data); // 獲取接口數據 // }).catch(error=>{ // console.log(error.response); // 獲取錯誤信息 // }) } } }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="vue.js"></script> <script src="axios.js"></script> </head> <body> <div id="app"></div> <script> // XMLHttpRequest的使用有4個步驟 // 1. 實例化XMLHttpRequest var xhr = new XMLHttpRequest(); // 獲得ajax對象 // 2. 建立http請求 // 參數1: 字符串,http請求動做,通常是get,post // 參數2: 字符串,請求的服務端的url地址 xhr.open("get","http://wthrcdn.etouch.cn/weather_mini?city=北京") // 3. 發送請求 // 參數1:字符串,當post請求有請求體數據,則須要把數據填寫到這裏 // 例如:xhr.send("name=xiaoming&age=17") xhr.send() // 4. 獲取服務端響應數據 xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ // xhr.readyState表示xhr的狀態碼,1表示ajx對象剛建立,2表示ajax請求組裝完成,3表示ajax請求已發送到服務端,4表示客戶端已經獲取到服務端返回的數據結果 if(xhr.status == 200){ // xhr.status http響應狀態碼 data = JSON.parse(xhr.responseText); console.log( data ); } } } </script> </body> </html>
ajax本質上仍是javascript,是運行在瀏覽器中的腳本語言,因此會被受到瀏覽器的同源策略所限制。
前端地址:http://www.oldboy.cn/index.html |
是否同源 | 緣由 |
---|---|---|
http://www.oldboy.cn/user/login.html |
是 | 協議、域名、端口相同 |
http://www.oldboy.cn/about.html |
是 | 協議、域名、端口相同 |
https://www.oldboy.cn:443/user/login.html |
否 | 協議不一樣 ( https和http ) |
http:/www.oldboy.cn:5000/user/login.html |
否 | 端口 不一樣( 5000和80) |
http://bbs.oldboy.cn/user/login.html |
否 | 域名不一樣 ( bbs和www ) |
同源策略針對ajax的攔截,代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> <script src="js/axios.js"></script> </head> <body> <div id="app"> <input type="text" v-model="music"><button @click="get_music">查詢歌曲</button> </div> <script> var vm = new Vue({ el:"#app", data:{ music:"", // 歌曲標題 }, methods:{ get_music(){ axios.get(`http://tingapi.ting.baidu.com/v1/restserver/ting`,{ params:{ method:"baidu.ting.search.catalogSug", query:this.music, } }).then(response=>{ console.log("查詢數據成功!"); }).catch(error=>{ console.log("查詢數據失敗!"); }) } } }) </script> </body> </html>
上面代碼運行錯誤以下:
Access to XMLHttpRequest at 'http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.catalogSug&query=%E6%88%91%E7%9A%84%E4%B8%AD%E5%9B%BD%E5%BF%83' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
上面錯誤,關鍵詞:Access-Control-Allow-Origin
只要出現這個關鍵詞,就是訪問受限。出現同源策略的攔截問題。
ajax跨域(跨源)方案:服務端受權[CORS],jsonp,服務端代理
CORS是一個W3C標準,全稱是"跨域資源共享",它容許瀏覽器向跨源的後端服務器發出ajax請求,從而克服了AJAX只能同源使用的限制。
實現CORS主要依靠後端服務器中響應數據中設置響應頭信息返回的。
django的視圖[僞代碼]
def post(request):
response = new Response()
response .set_header("Access-Control-Allow-Origin","http://localhost:63342")
return response;
// 在響應行信息裏面設置如下內容:
Access-Control-Allow-Origin: ajax所在的域名地址
Access-Control-Allow-Origin: www.oldboy.cn # 表示只容許www.oldboy.cn域名的客戶端的ajax跨域訪問
// * 表示任意源,表示容許任意源下的客戶端的ajax均可以訪問當前服務端信息
Access-Control-Allow-Origin: *
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button onclick="getdata()">獲取數據</button> <script> function getdata(){ // 發送jsonp // 1. 建立script標籤,並制定src爲api地址,並追加到head標籤中 let script = document.createElement("script") // callback 就是服務端配合咱們返回調用的方法名,把服務端數據做爲參數給callback的值對應方法進行調用 script.src="http://cache.video.iqiyi.com/jp/avlist/202861101/1/?callback=setdata"; document.head.append(script) console.log(script) } function setdata(data){ // 這裏就是響應數據的處理方法。 console.log(data);//把數據顯示到html頁面 } </script> </body> </html>
總結:
0. 同源策略:瀏覽器的一種保護用戶數據的一種安全機制。
瀏覽器會限制ajax不能跨源訪問其餘源的數據地址。
同源:判斷兩個通訊的地址之間,是否協議,域名[IP],端口一致。
ajax: http://127.0.0.1/index.html
api數據接口: http://localhost/index
這兩個是同源麼?不是同源的。是否同源的判斷依據不會根據電腦來判斷,而是經過協議、域名、端口的字符串是否來判斷。
1. ajax默認狀況下會受到同源策略的影響,一旦受到影響會報錯誤以下:
No 'Access-Control-Allow-Origin' header is present on the requested resource
2. 解決ajax只能同源訪問數據接口的方式:
1. CORS,跨域資源共享,在服務端的響應行中設置:
Access-Control-Allow-Origin: 容許訪問的域名地址
2. jsonp
所謂的jsonp本質上來講不是ajax技術,jsonp的核心實現是依靠script自己加載外部js文件來實現的。
固然,實現jsonp技術,也須要服務端的配合
3. 是否服務端代理
思路:經過python來請求對應的服務器接口,客戶端和python這邊處於同源,那麼就實現了服務端代理
1. 在做業.html的代碼基礎上,完成商品數量的加減,注意商品數量若是低於0個,則自動刪除當前商品
2. 在做業.html的代碼基礎上,完成購物車總價格的計算。
3. 使用ajax獲取北京天氣,並把昨天和將來5每天氣狀況以表格格式展現到html頁面中。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> #goods table{ width: 600px; border:1px solid #000; border-collapse: collapse; } #goods td,#goods th{ border: 1px solid #000; } #goods .box{ position: fixed; top: 0; left: 0; right: 0; bottom: 0; margin: auto; background-color: #eee; width: 280px; height: 160px; padding: 40px 80px; } </style> <script src="vue.js"></script> </head> <body> <div id="goods"> <button @click="is_show=true;goods_index=-1;">添加商品</button> <table> <tr> <th>商品編號</th> <th>商品標題</th> <th>商品數量</th> <th>商品價格</th> <th>操做</th> </tr> <tr v-for="goods,index in goods_list"> <td>{{index+1}}</td> <td>{{goods.name}}</td> <td> <button @click="sub(index)">-</button> <input type="text" @keyup="check(index)" size="2" v-model="goods.num"> <button @click="goods.num++">+</button> </td> <td>{{goods.price.toFixed(2)}}</td> <td> <button @click="update(index)">編輯</button> <button @click="del(index)">刪除</button> </td> </tr> <tr> <td colspan="5">總計: {{total}}元</td> </tr> </table> <div class="box" v-show="is_show"> 商品標題: <input type="text" v-model="goods_name"><br><br> 商品數量: <input type="text" v-model="goods_num"><br><br> 商品價格: <input type="text" v-model="goods_price"><br><br> <button @click="save">保存</button> <button @click="cancel">取消</button> </div> </div> <script> var vm = new Vue({ el:"#goods", data:{ is_show:false, goods_name:"", goods_num:"", goods_price:"", goods_index:-1, // 當前本次操做的商品信息[-1表示新增,大於0表示編輯] goods_list:[ {"name":"python入門","num":27,"price":150}, {"name":"python進階","num":21,"price":100}, {"name":"python高級","num":17,"price":75}, {"name":"python研究","num":37,"price":60}, {"name":"python放棄","num":57,"price":110}, ] }, computed:{ total(){ // 計算購物車中全部商品總價格 let sum = 0; /* for ... in 時,遍歷出來的數據是當前數組的下標或者對象的屬性名稱 for ... of 時,遍歷出來的數據是當前數組的成員或者對象的屬性值 */ for(let goods of this.goods_list){ sum += parseInt(goods.num) * parseFloat(goods.price); } return sum.toFixed(2); } }, methods:{ check(index){ var goods = this.goods_list[index]; if(goods.num<1){ this.goods_list.splice(index,1); } }, sub(index){ // 商品數量的減小 var goods = this.goods_list[index]; goods.num--; // 若是當前商品數量爲0,則刪除商品 if(goods.num<1){ this.goods_list.splice(index,1); } }, save(){ // 保存數據[添加數據] if(this.goods_index==-1){ this.goods_list.push({ "name":this.goods_name, "num":parseInt(this.goods_num), "price":parseFloat(this.goods_price), }); }else{ // 能在編輯商品的時候,修改數量爲0的時候也刪除商品嗎 if(this.goods_num<1){ this.goods_list.splice(this.goods_index,1); }else{ this.goods_list[this.goods_index].name=this.goods_name; this.goods_list[this.goods_index].num=parseInt(this.goods_num); this.goods_list[this.goods_index].price=parseFloat(this.goods_price); } } this.cancel(); }, cancel(){ this.is_show=false; this.goods_index= -1; this.goods_name= ""; this.goods_num= ""; this.goods_price= ""; }, del(index){ // 刪除數據 this.goods_list.splice(index,1); }, update(index){ // 先彈窗 this.is_show=true; // 顯示當前編輯的商品信息 this.goods_index=index; this.goods_name=this.goods_list[index].name; this.goods_num=this.goods_list[index].num; this.goods_price=this.goods_list[index].price; // 當用戶點擊保存時,修改對應數據 } } }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="vue.js"></script> <script src="axios.js"></script> </head> <body> <div id="app"> <input type="text" v-model="city"> <button @click="get_weather">獲取天氣</button> </div> <script> let vm = new Vue({ el: "#app", data: { city: '上海' }, // 在初始化的時候自動發送ajax獲取數據 methods: { get_weather() { axios.get('http://wthrcdn.etouch.cn/weather_mini?', { params: {city: this.city}, headers: {}, }).then(response => { console.log(response.data) }).catch(error => { console.log('請求失敗') }) } } }); </script> </body> </html>