什么是 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)體
模板引擎
- 選擇一個模板引擎
http://github.com/tj/consolidate.js#supported-template-engines - 下載模板引擎JS文件
- 引入到頁面中
- 準(zhǔn)備一個模板
- 準(zhǔn)備一個數(shù)據(jù)
- 通過模板引擎的 JS 提供的一個函數(shù)將模板和數(shù)據(jù)整合得到渲染結(jié)果 HTML
- 將渲染結(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)
- 能發(fā)出去
- 能收回來
// 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: *');