AJAX = Asynchronous JavaScript and XML。核心:XMLHttpRequest (XHR) 異步請求 + DOM 局部更新。
優勢:無刷新體驗、減少頻寬、表單即時校驗、自動保存草稿等。
| readyState | 含義 |
|---|---|
| 0 | UNSENT,未調用 open() |
| 1 | OPENED,已 open(),未 send() |
| 2 | HEADERS_RECEIVED,收到響應頭 |
| 3 | LOADING,響應體下載中 |
| 4 | DONE,完成 |
判斷邏輯:if (xhr.readyState === 4 && xhr.status === 200) 才處理響應。
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>AJAX Demo</title></head><body>
<h1>員工查詢</h1>
<input id="keyword" placeholder="工號"> <button id="search">查詢</button>
<p id="searchResult"></p>
<h1>員工新建</h1>
<input id="staffName" placeholder="姓名"><br>
<input id="staffNumber" placeholder="工號"><br>
<select id="staffSex"><option>女</option><option>男</option></select><br>
<input id="staffJob" placeholder="職位"><br>
<button id="save">保存</button>
<p id="createResult"></p>
<script>
// 通用請求封裝
function request(opt) {
var xhr = new XMLHttpRequest();
xhr.open(opt.method, opt.url, true);
if (opt.method === 'POST') xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) return;
if (xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
opt.success(data);
} else {
opt.error(xhr.status);
}
};
xhr.send(opt.data || null);
}
// 綁定事件
document.getElementById('search').onclick = function() {
var no = document.getElementById('keyword').value;
request({
method: 'GET',
url: 'serverjson.php?number=' + encodeURIComponent(no),
success: function(d) { document.getElementById('searchResult').innerHTML = d.success ? d.msg : '錯誤:' + d.msg; },
error: function(s) { alert('HTTP ' + s); }
});
};
document.getElementById('save').onclick = function() {
var data = 'name=' + encodeURIComponent(document.getElementById('staffName').value)
+ '&number=' + encodeURIComponent(document.getElementById('staffNumber').value)
+ '&sex=' + encodeURIComponent(document.getElementById('staffSex').value)
+ '&job=' + encodeURIComponent(document.getElementById('staffJob').value);
request({
method: 'POST',
url: 'serverjson.php',
data: data,
success: function(d) { document.getElementById('createResult').innerHTML = d.success ? d.msg : '錯誤:' + d.msg; },
error: function(s) { alert('HTTP ' + s); }
});
};
</script>
</body></html>
<?php
header('Content-Type: application/json;charset=utf-8');
header('Access-Control-Allow-Origin: *'); // 跨域演示
$staff = [
['name'=>'洪七','number'=>'101','sex'=>'男','job'=>'總經理'],
['name'=>'郭靖','number'=>'102','sex'=>'男','job'=>'開發工程師'],
['name'=>'黃蓉','number'=>'103','sex'=>'女','job'=>'產品經理'],
];
if ($_SERVER['REQUEST_METHOD'] === 'GET') { search(); }
elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { create(); }
function search() {
if (empty($_GET['number'])) exit(json_encode(['success'=>false,'msg'=>'參數錯誤']));
global $staff;
foreach ($staff as $v) if ($v['number'] == $_GET['number']) exit(json_encode(['success'=>true,'msg'=>"找到員工:{$v['number']} {$v['name']} {$v['sex']} {$v['job']}"]));
exit(json_encode(['success'=>false,'msg'=>'未找到']));
}
function create() {
foreach (['name','number','sex','job'] as $k) if (empty($_POST[$k])) exit(json_encode(['success'=>false,'msg'=>'信息不全']));
// TODO: 入庫
exit(json_encode(['success'=>true,'msg'=>"員工:{$_POST['name']} 保存成功"]));
}
$.ajax({
type: 'GET',
url: 'serverjson.php',
data: {number: $('#keyword').val()},
dataType: 'json',
success: function(d) { $('#searchResult').html(d.success ? d.msg : '錯誤:'+d.msg); },
error: function(xhr) { alert('HTTP '+xhr.status); }
});
$.ajax({
type: 'POST',
url: 'serverjson.php',
data: {
name: $('#staffName').val(),
number: $('#staffNumber').val(),
sex: $('#staffSex').val(),
job: $('#staffJob').val()
},
dataType: 'json',
success: function(d) { $('#createResult').html(d.success ? d.msg : '錯誤:'+d.msg); },
error: function(xhr) { alert('HTTP '+xhr.status); }
});
encodeURIComponent() 必須用於 GET 參數與 POST Body 字串拼接,防止 & = + 等特殊字符破壞結構。application/x-www-form-urlencoded 對應 $_POST;若發 JSON 需 application/json + file_get_contents('php://input') 解析。Access-Control-Allow-Origin、Allow-Methods、Allow-Credentials;前端 xhr.withCredentials = true 發送 Cookie。JSON.parse 替代 eval,防 XSS。xhr.abort(),組件卸載時調用防內存洩漏。fetch() + async/await、axios、ky,更優雅、支持攔截器、自動 JSON、取消令牌。