Ajax

什么是 Ajax ?

Ajax 就是瀏覽器提供的一套API, 可以通過 JavaScript 調(diào)用, 從而實現(xiàn)通過代碼控制請求與相應(yīng), 實現(xiàn)網(wǎng)絡(luò)編程

優(yōu)點: 相比傳統(tǒng)網(wǎng)絡(luò)請求(數(shù)據(jù)寫在 HTML 中), 請求只發(fā)生在頁面區(qū)域內(nèi), 不會重新加載整個頁面(像一些引入內(nèi)容等), 請求速度會更快

缺點: 不利于 SEO, 就是說不利于搜索引擎優(yōu)化, 目前百度不支持抓取 JavaScript 里的內(nèi)容, 只支持抓取 HTML 中的內(nèi)容, 國外已經(jīng)支持抓取 JavaScript 里的內(nèi)容

注意: 涉及到 Ajax 操作的頁面不能使用文件協(xié)議訪問(文件的方法訪問)

快速上手

發(fā)送 GET 請求

// xhr 就類似于瀏覽器的作用(發(fā)送請求接收響應(yīng))
var xhr = new XMLHttpRequest()

// 獲取相應(yīng)狀態(tài)碼
console.log(xhr.readyState) // ==> 0 : 初始化, 請求代理對象

// 以 GET 的方式發(fā)送請求
xhr.open('GET', 'ajax.php')
console.log(xhr.readyState) // ==> 1 : open 方法已經(jīng)調(diào)用, 建立一個與服務(wù)端特定端口的連接

// 開始請求, 沒有返回值
xhr.send()  
console.log(xhr.readyState)// ==> 1 : 這里也是1

// 接收請求(監(jiān)聽狀態(tài)碼改變事件)
xhr.onreadystatechange = function () {
  /* 
    ==> 2,3,4 : 
    2 指已經(jīng)接受到相應(yīng)報文的響應(yīng)頭, 此時只接受到了響應(yīng)頭
    3 指正在下載相應(yīng)報文的響應(yīng)體, 有可能響應(yīng)體為空, 有可能不完整
    4 指一切ok, 可以執(zhí)行后續(xù)的邏輯了
  */
  if (this.readyState !== 4) return
  
  //獲取相應(yīng)狀態(tài)描述
  console.log(this.responseText)
  console.log(xhr.readyState)
}

發(fā)送 POST 請求

  // 設(shè)置請求信息
        
var xhr = new XMLHttpRequest()

xhr.open('POST', 'ajax.php') // 設(shè)置請求行

xhr.setRequestHeader('Foo', 'Bar') // 設(shè)置一個請求頭

// 一旦你的請求體是 urlencoded 格式的內(nèi)容, 一定要設(shè)置請求頭中 Content-Type 為對應(yīng)的格式
xhr.setRequestHeader('content-Type','application/x-www-from-urlencoded')

xhr.send('key1=value1&key2=value2') // 以urlencoded 格式設(shè)置請求體

xhr.onreadystatechange = function() {
  if (this.readyState !=== 4) return
  console.log(this.responseText)
}

this.responseText 永遠獲取的都是字符串形式的響應(yīng)體

模板引擎

  1. 選擇一個模板引擎
    http://github.com/tj/consolidate.js#supported-template-engines
  2. 下載模板引擎JS文件
  3. 引入到頁面中
  4. 準(zhǔn)備一個模板
  5. 準(zhǔn)備一個數(shù)據(jù)
  6. 通過模板引擎的 JS 提供的一個函數(shù)將模板和數(shù)據(jù)整合得到渲染結(jié)果 HTML
  7. 將渲染結(jié)果的 HTML 設(shè)置到默認元素的 innerHTML

利用模板引擎動態(tài)生成表格數(shù)據(jù) (客戶端)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <table id="demo"></table>
    
  <!-- 導(dǎo)入模板 JS 文件 -->
  <script src="template-web.js"></script>
  <!-- 模板創(chuàng)建元素 -->
  <script id="tmpl" type="text/html">
    // each 遍歷 comments 中的數(shù)據(jù), 動態(tài)的生成表格數(shù)據(jù) 
    {{ each comments }}
    // each 內(nèi)部 $value 拿到的是當(dāng)前被遍歷的那個元素, $index拿到的是下標(biāo) 
    <tr>
      <td>{{$value.name}}</td>
      <td>{{$value.age}}</td>
    </tr>
    {{/each}}
  </script>

  <!-- ajax獲取服務(wù)端的json數(shù)據(jù) -->
  <script type="text/javascript">
    var xhr = new XMLHttpRequest()
    xhr.open('GET','art-template.php')
    xhr.send()
    xhr.onreadystatechange = function(){
      if (this.readyState !== 4) return
      // 將獲取的json數(shù)據(jù)解析
      var res = JSON.parse(this.responseText)

      // 模板所需數(shù)據(jù)
      var context = {comments:res}
      var html1 = template('tmpl',context)
      console.log(html1)

      document.getElementById('demo').innerHTML = html1
    }

  </script>
</body>
</html>

服務(wù)端

<?php 
  // 設(shè)置訪問頭格式
  header('Content-Type: application/json');
?>

// json數(shù)據(jù)
[
  { "name": "張三", "age": "1" }, 
  { "name": "李四", "age": "2" }, 
  { "name": "王五", "age": "3" }  
]

jQuery 中 Ajax 的使用

底層接口的使用

$.ajax({
  url: 'time.php',
  type: 'get',
  // 用于提交到服務(wù)端的參數(shù), 如果是 get 請求就通過 url 傳遞, 如果是 post 請求就通過請求體傳遞
  data: { id: 1, name: '張三' },
  // 用于設(shè)置響應(yīng)體的類型, 和data參數(shù)沒關(guān)系
  dataType: 'json',
  success: function (res) {
    console.log(res)
  }
})

相關(guān)函數(shù)

$.ajax({
  url: 'time.php',
  type: 'get',
  beforeSend: function(xhr) {
    // 在所有發(fā)送請求的操作(open, send)之前執(zhí)行
    console.log(xhr)
  },
  success: function(res) {
    // 隱藏 loading, 只有請求成功(狀態(tài)碼為200)才會執(zhí)行
    console.log(res)
  },
  error: function(xhr) {
  // 隱藏loading, 和success相反
    console.log(xhr)
  },
  complete: function(xhr) {
    // 不管是成功還是失敗都會執(zhí)行這個函數(shù), 相當(dāng)于 success 和 error 的結(jié)合體
    console.log(xhr)
  }
})

高度封裝的函數(shù)

$.get('json.php', { id: 1 }, function(res) {
  console.log(res)
})

$.post('json.php', { id: 1 }, function(res) {
  console.log(res)
})

// 轉(zhuǎn)換成json對象
$.getJSON('json.php', { id: 1 }, function(res) {
  console.log(res)
})

跨域

同源策略: 同源是指協(xié)議, 端口, 域名完全相同, 默認只有同源的地址才能相互通過 Ajax 發(fā)送請求, 不同源地址之間請求我們稱之為跨域請求

JS 的方法

  • 所有的請求方式: ajax、img、link、script桨踪、iframe

  • 校驗?zāi)繕?biāo)

    1. 能發(fā)出去
    2. 能收回來
// ajax 的方式請求(默認不能發(fā)送跨域請求)

// img的方式發(fā)送請求
var img = new Image()
img.src = '不同源地址'
// 結(jié)論: 可以發(fā)送不同源地址之間的請求, 但是無法拿到響應(yīng)結(jié)果

// link 真正的定義: 鏈入一個文檔, 通過 rel 屬性申明鏈入的文檔與當(dāng)前文檔之間的關(guān)系
var link = document.createElement('link')
link.rel = 'stylesheet'
link.src = '地址'
document.body.appendChild('link') 
// 結(jié)論: 可以發(fā)送不同源地址之間的請求, 但是無法拿到響應(yīng)結(jié)果

JSONP

客戶端

var script = document.createElement('script')
script.src = '服務(wù)端地址'
document.body.appendChild('script') 
function callback(data) {
  console.log(data)
}

服務(wù)端

<?php
header('Content-Type:applacation/javascript');
$json = { "name": "zhangsan", "age": 14 };
echo callback({ $json });
?>

結(jié)論: 可以發(fā)送不同源地址之間的請求, 但是無法拿到相應(yīng)結(jié)果, 可以借助于能夠作為 JS 執(zhí)行來拿到結(jié)果
服務(wù)端把 Content—Type 設(shè)置成 javascript, 并把結(jié)果包裝在一個函數(shù)內(nèi), 且又服務(wù)端調(diào)用該函數(shù), 客戶端通過這個函數(shù)拿到結(jié)果, 這個過程叫做 JSONP

jQuery 的方法

jsonp 和 Ajax 沒有必然的聯(lián)系, 只需要把 dataType 設(shè)置成 jsonp 就可以跨域

$.ajax ({
  url: '服務(wù)器地址',
  dataType:'jsonp',
  success: function (res) {
    console.log(res)
  }
})

CORS

Cross Origin Resource Share(跨域資源共享)

這種方案無需客戶端做出任何變化, 只是在被請求的服務(wù)端響應(yīng)的時候添加一個 Access-Content-Allow-Origin 的響應(yīng)頭, 表示這個資源是否允許指定域請求

//允許遠端訪問
header('Access-Content-Allow-Origin: *');
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末紧索,一起剝皮案震驚了整個濱河市淤袜,隨后出現(xiàn)的幾起案子踱讨,更是在濱河造成了極大的恐慌峭梳,老刑警劉巖碾篡,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虱而,死亡現(xiàn)場離奇詭異,居然都是意外死亡开泽,警方通過查閱死者的電腦和手機牡拇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來穆律,“玉大人惠呼,你說我怎么就攤上這事÷驮牛” “怎么了剔蹋?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辅髓。 經(jīng)常有香客問我泣崩,道長少梁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任矫付,我火速辦了婚禮凯沪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘买优。我一直安慰自己著洼,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布而叼。 她就那樣靜靜地躺著,像睡著了一般豹悬。 火紅的嫁衣襯著肌膚如雪葵陵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天瞻佛,我揣著相機與錄音脱篙,去河邊找鬼。 笑死伤柄,一個胖子當(dāng)著我的面吹牛绊困,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播适刀,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼秤朗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了笔喉?” 一聲冷哼從身側(cè)響起取视,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎常挚,沒想到半個月后作谭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡奄毡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年折欠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吼过。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡锐秦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出那先,到底是詐尸還是另有隱情农猬,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布售淡,位于F島的核電站斤葱,受9級特大地震影響慷垮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜揍堕,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一料身、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衩茸,春花似錦芹血、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至囊蓝,卻和暖如春饿悬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背聚霜。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工狡恬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝎宇。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓弟劲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親姥芥。 傳聞我的和親對象是個殘疾皇子兔乞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Ajax的基本概念及使用 同步&異步 同步:必須等待前面的任務(wù)完成,才能繼續(xù)后面的任務(wù)凉唐; 異步:不受當(dāng)前主要任務(wù)的...
    magic_pill閱讀 1,955評論 0 5
  • AJAX概述 ajax是在瀏覽器端進行網(wǎng)絡(luò)編程(發(fā)送請求报嵌、接受響應(yīng))的技術(shù)方案,可以通過 js 直接獲取服務(wù)端最新...
    GongShengM閱讀 345評論 0 0
  • 一熊榛、HTTP服務(wù) 1.1 C/S和B/S B/S架構(gòu):即Broswer锚国、Server,將所有的服務(wù)都可以通過瀏覽器...
    福爾摩雞閱讀 687評論 0 4
  • 1. 介紹 1.1 Ajax介紹 Ajax的全稱是Asynchronous JavaScript and XML ...
    riverhh閱讀 439評論 1 2
  • AJAX 概述 背景 “JavaScript 對我們而已能力有限”玄坦,我們目前所了解到的 Web 所提供的 API ...
    這是這時閱讀 2,043評論 0 2