“AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。 ”
AJAX 是什么 ?
- AJAX = 异步 JavaScript 和 XML
- AJAX 是一种用于创建快速动态网页的技术
- 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
XMLHttpRequest 对象
XMLHttpRequest 是 AJAX 的基础,用于在后台和服务器交换数据,这样可以在不刷新页面的情况下,加载页面。
创建 XMLHttpRequest 对象
为了应对所有的现代浏览器,包括 IE5 和 IE6,需要检查浏览器是否支持 XMLHttpRequest 对象,如果支持,则创建 XMLHttpRequest 对象,如果不支持,则创建 ActiveXObject:
var request ;
if(window.XMLHttpRequest){
// IE7+, Firefox, Chrome, Opera, Safari
request = new XMLHttpRequest();
} else {
// IE5, IE6
request = new ActiveXObject("Microsoft.XMLHTTP");
}
HTTP 请求
HTTP 是计算机通过网络进行通信的规则,主要是使客户端能够向服务器发起一种HTTP请求。
一个完整的 HTTP 请求过程,通常有 7 个步骤:
- 建立 TCP 连接
- Web 浏览器向 Web 服务器发送请求命令
- Web 浏览器发送请求头部信息
- Web 服务器应答
- Web 服务器发送应答头信息
- Web 服务器向浏览器发送数据
- Web 服务器关闭 TCP 连接
一个HTTP请求一般由四部分组成:
- HTTP请求的方法或动作,比如 GET 或者 POST
- 正在请求的 URL
- 请求头,包含一些客户端的环境信息,身份验证
- 请求体,请求正文,包含客户提交的查询字符串信息,表单信息
GET
- 一般用于信息获取
- 使用 URL 传递参数
- 对所发送的信息数量也有限,一般是2000个字符
POST
- 一般用于修改服务器上的资源
- 对所发送信息的数量无限制
XMLHttpReques 发送请求
open(method, url, async)
method 发送的方法 : GET、POST
url 请求的地址
async 请求同步/异步, 默认为 true
send(string)
例如:
request.open("GET", "get.php", true)
request.send();
// POST 请求
request.open("POST", "create.php", true)
// 设置 HTTP 的头信息
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
request.send("name=王二狗&sex=男")
XMLHttpRequest 取得响应
readyState 属性
0 : 请求未初始化, open 还没有调用
1 : 服务器连接已建立, open 已经调用
2 : 请求已接收, 也就是接收到头信息
3 : 请求处理中, 也就是接收到响应主体
4 : 请求完成, 且响应已就绪, 响应完成
// 创建 XHR 对象
var request = new XMLHttpRequest();
// 调用 open 方法
request.open("GET", "get.php", true);
// send 一些数据
request.send();
// 监听这个过程,判断响应是否完成
request.onreadystatechange = function(){
if(request.readyState === 4 && request.status === 200){
// do something
}
}
AJAX 简单的例子
纯 HTML 页面,用来实现员工查询和新建页面
php 页面,用来实现查询员工和新建员工的后台接口
服务器端的代码
<?php
//设置页面内容是html编码格式是utf-8
header("Content-Type: text/plain;charset=utf-8");
//header("Content-Type: application/json;charset=utf-8");
// header("Content-Type: text/xml;charset=utf-8");
//header("Content-Type: text/html;charset=utf-8");
//header("Content-Type: application/javascript;charset=utf-8");
//定义一个多维数组,包含员工的信息,每条员工信息为一个数组
$staff = array
(
array("name" => "洪七", "number" => "101", "sex" => "男", "job" => "总经理"),
array("name" => "郭靖", "number" => "102", "sex" => "男", "job" => "开发工程师"),
array("name" => "黄蓉", "number" => "103", "sex" => "女", "job" => "产品经理")
);
//判断如果是get请求,则进行搜索;如果是POST请求,则进行新建
//$_SERVER是一个超全局变量,在一个脚本的全部作用域中都可用,不用使用global关键字
//$_SERVER["REQUEST_METHOD"]返回访问页面使用的请求方法
if ($_SERVER["REQUEST_METHOD"] == "GET") {
search();
} elseif ($_SERVER["REQUEST_METHOD"] == "POST"){
create();
}
//通过员工编号搜索员工
function search(){
//检查是否有员工编号的参数
//isset检测变量是否设置;empty判断值为否为空
//超全局变量 $_GET 和 $_POST 用于收集表单数据
if (!isset($_GET["number"]) || empty($_GET["number"])) {
echo "参数错误";
return;
}
//函数之外声明的变量拥有 Global 作用域,只能在函数以外进行访问。
//global 关键词用于访问函数内的全局变量
global $staff;
//获取number参数
$number = $_GET["number"];
$result = "没有找到员工。";
//遍历$staff多维数组,查找key值为number的员工是否存在,如果存在,则修改返回结果
foreach ($staff as $value) {
if ($value["number"] == $number) {
$result = "找到员工:员工编号:" . $value["number"] . ",员工姓名:" . $value["name"] .
",员工性别:" . $value["sex"] . ",员工职位:" . $value["job"];
break;
}
}
echo $result;
}
//创建员工
function create(){
//判断信息是否填写完全
if (!isset($_POST["name"]) || empty($_POST["name"])
|| !isset($_POST["number"]) || empty($_POST["number"])
|| !isset($_POST["sex"]) || empty($_POST["sex"])
|| !isset($_POST["job"]) || empty($_POST["job"])) {
echo "参数错误,员工信息填写不全";
return;
}
//TODO: 获取POST表单数据并保存到数据库
//提示保存成功
echo "员工:" . $_POST["name"] . " 信息保存成功!";
}
客户端的实现
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Demo</title>
<style>
body, input, select, button, h1 {
font-size: 28px;
line-height:1.7;
}
</style>
</head>
<body>
<h1>员工查询</h1>
<label>请输入员工编号:</label>
<input type="text" id="keyword" />
<button id="search">查询</button>
<p id="searchResult"></p>
<h1>员工新建</h1>
<label>请输入员工姓名:</label>
<input type="text" id="staffName" /><br>
<label>请输入员工编号:</label>
<input type="text" id="staffNumber" /><br>
<label>请选择员工性别:</label>
<select id="staffSex">
<option>女</option>
<option>男</option>
</select><br>
<label>请输入员工职位:</label>
<input type="text" id="staffJob" /><br>
<button id="save">保存</button>
<p id="createResult"></p>
<script>
// GET 请求
document.getElementById("search").onclick = function(){
// 发送 ajax 请求
var request = new XMLHttpRequest();
request.open("GET", "server.php?number=" + document.getElementById("keyword").value);
request.send();
request.onreadystatechange = function(){
// 判断请求是否完成
if(request.readyState === 4){
// 判断请求是否成功
if(request.status === 200){
document.getElementById("searchRequest").innerHTML = request.responseText;
} else {
alert("发生错误" + request.status);
}
}
}
}
// POST 请求
document.getElementById("save").onclick = function(){
// 发送 ajax 查询请求并处理
var request = new XMLHttpRequest();
request.open("POST", "service.php");
// 要发送的数据 data
var data = "name=" + document.getElementById("staffName").value
+ "&number=" + document.getElementById('staffNumber').value
+ "&sex=" + document.getElementById('staffSex').value
+ "&job=" + document.getElementById('staffJob').value;
// 这个必须设置,告诉浏览器处理的是表单
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.send(data);
request.onreadystatechange = function(){
// 判断请求是否完成
if(request.readyState === 4){
// 判断请求是否成功
if(request.status === 200){
document.getElementById("createRequest").innerHTML = request.responseText;
} else {
alert("发生错误" + request.status);
}
}
}
}
</script>
</body>
</html>
以上这个例子是用纯文本的方式来写的,不太灵活,我们现在一般使用 json 的方式来数据,json的方式比较灵活,易于解析。
JSON
JSON : JavaScript 对象表示法( JavaScript Object Notation )
基本概念
JSON 是储存和交换文本信息的语法,采用键值对的方式来组织,易于编写和阅读,也易于机器解析
JSON 是独立于语言的,不管什么语言都可以解析 json,只要按照 json 方式来解析就行
**JSON 数据的书写方式 : 名称/值对
名称/值对组合中的名称写掐面(在双引号中),值对写在后面(同样在双引号中),中间用冒号隔开
比如:
{
"person" : [
{ "name" : "Lyf", "age" : "20" },
{ "name" : "Job", "age" : "50"}
]
}
JSON 解析和格式化
eval()
和 JSON.parse()
在代码中使用 eval是很危险的,尽可能的使用 JSON.parse() 方法解析字符串,该方法还可以捕捉 json 中的语法错误。
eval() 的方式解析
var jsonData = {
"person" : [
{ "name" : "Lyf", "age" : "20" },
{ "name" : "Job", "age" : "50"}
]
};
var jsonObj = eval('(' + jsonData +')');
alert(jsonObj.person[0].name); // Lyf
JSON.parse() 的方式
var jsonData = {
"person" : [
{ "name" : "Lyf", "age" : "20" },
{ "name" : "Job", "age" : "50"}
]
};
var jsonObj= JSON.parse(jsonData);
alert(jsonObj.person[0].name); // Lyf
JSON 在线格式化和校验网站 JSONLint
用 JSON 的方式改造之前的例子
服务器端稍稍改造
<?php
//设置页面内容是html编码格式是utf-8
header("Content-Type: text/plain;charset=utf-8");
//header("Content-Type: application/json;charset=utf-8");
//header("Content-Type: text/xml;charset=utf-8");
//header("Content-Type: text/html;charset=utf-8");
//header("Content-Type: application/javascript;charset=utf-8");
//定义一个多维数组,包含员工的信息,每条员工信息为一个数组
$staff = array
(
array("name" => "洪七", "number" => "101", "sex" => "男", "job" => "总经理"),
array("name" => "郭靖", "number" => "102", "sex" => "男", "job" => "开发工程师"),
array("name" => "黄蓉", "number" => "103", "sex" => "女", "job" => "产品经理")
);
//判断如果是get请求,则进行搜索;如果是POST请求,则进行新建
//$_SERVER是一个超全局变量,在一个脚本的全部作用域中都可用,不用使用global关键字
//$_SERVER["REQUEST_METHOD"]返回访问页面使用的请求方法
if ($_SERVER["REQUEST_METHOD"] == "GET") {
search();
} elseif ($_SERVER["REQUEST_METHOD"] == "POST"){
create();
}
//通过员工编号搜索员工
function search(){
//检查是否有员工编号的参数
//isset检测变量是否设置;empty判断值为否为空
//超全局变量 $_GET 和 $_POST 用于收集表单数据
if (!isset($_GET["number"]) || empty($_GET["number"])) {
// 这里改成 JSON 的形式
echo '{"success":false,"msg":"参数错误"}';
return;
}
//函数之外声明的变量拥有 Global 作用域,只能在函数以外进行访问。
//global 关键词用于访问函数内的全局变量
global $staff;
//获取number参数
$number = $_GET["number"];
// 这里改成 JSON 的形式
$result = '{"success":false,"msg":"没有找到员工。"}';
//遍历$staff多维数组,查找key值为number的员工是否存在,如果存在,则修改返回结果
foreach ($staff as $value) {
if ($value["number"] == $number) {
// 这里改成 JSON 的形式
$result = '{"success":true,"msg":"找到员工:员工编号:' . $value["number"] .
',员工姓名:' . $value["name"] .
',员工性别:' . $value["sex"] .
',员工职位:' . $value["job"] . '"}';
break;
}
}
echo $result;
}
//创建员工
function create(){
//判断信息是否填写完全
if (!isset($_POST["name"]) || empty($_POST["name"])
|| !isset($_POST["number"]) || empty($_POST["number"])
|| !isset($_POST["sex"]) || empty($_POST["sex"])
|| !isset($_POST["job"]) || empty($_POST["job"])) {
echo '{"success":false,"msg":"参数错误,员工信息填写不全"}';
return;
}
//TODO: 获取POST表单数据并保存到数据库
//提示保存成功
// 这里改成 JSON 的形式
echo '{"success":true,"msg":"员工:' . $_POST["name"] . ' 信息保存成功!"}';
}
?>
服务器端的代码
<script>
// GET 请求
document.getElementById("search").onclick = function(){
// 发送 ajax 请求
var request = new XMLHttpRequest();
request.open("GET", "server.php?number=" + document.getElementById("keyword").value);
request.send();
request.onreadystatechange = function(){
// 判断请求是否完成
if(request.readyState === 4){
// 判断请求是否成功
if(request.status === 200){
// 解析服务器端的数据
var data = JSON.parse(request.responseText);
if(data.success){
document.getElementById("searchRequest").innerHTML = data.msg;
} else {
document.getElementById("searchRequest").innerHTML = "出现错误" + data.msg;
}
} else {
alert("发生错误" + request.status);
}
}
}
}
// POST 请求
document.getElementById("save").onclick = function(){
// 发送 ajax 查询请求并处理
var request = new XMLHttpRequest();
request.open("POST", "service.php");
// 要发送的数据 data
var data = "name=" + document.getElementById("staffName").value
+ "&number=" + document.getElementById('staffNumber').value
+ "&sex=" + document.getElementById('staffSex').value
+ "&job=" + document.getElementById('staffJob').value;
// 这个必须设置,告诉浏览器处理的是表单
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.send(data);
request.onreadystatechange = function(){
// 判断请求是否完成
if(request.readyState === 4){
// 判断请求是否成功
if(request.status === 200){
// 解析服务器端的数据
var data = JSON.parse(request.responseText);
if(data.success){
document.getElementById("createRequest").innerHTML = data.msg;
} else {
document.getElementById("createRequest").innerHTML = "出现错误" + data.msg;
}
} else {
alert("发生错误" + request.status);
}
}
}
}
</script>
用 jQuery 实现 AJAX
jQuery.ajax([settings])
type
类型, “POST” 或者 “GET”, 默认为 “GET”
url
发送请求的地址
data
是一个对象,连同请求发送到服务器的数据
dataType
预期服务器返回的数据类型。一般为 “json”
success
是一个方法,请求成功后的回调函数。传入返回后的数据,以及包含成功代码的字符串
error
是一个方法去,请求失败时调用的函数
用 jQuery 改写刚才的例子
// 引入 jQuery
<script src="http://apps.bdimg.com/libs/jquery/1.11.1/jquery.js"></script>
<script>
$(document).ready(function(){
$("#search").click(function(){
$.ajax({
type: "GET",
url: "http://127.0.0.1:8080/ajaxdemo/serverjson2.php?number=" + $("#keyword").val(),
dataType: "json",
success: function(data) {
if (data.success) {
$("#searchResult").html(data.msg);
} else {
$("#searchResult").html("出现错误:" + data.msg);
}
},
error: function(jqXHR){
alert("发生错误:" + jqXHR.status);
},
});
});
$("#save").click(function(){
$.ajax({
type: "POST",
url: "serverjson.php",
data: {
name: $("#staffName").val(),
number: $("#staffNumber").val(),
sex: $("#staffSex").val(),
job: $("#staffJob").val()
},
dataType: "json",
success: function(data){
if (data.success) {
$("#createResult").html(data.msg);
} else {
$("#createResult").html("出现错误:" + data.msg);
}
},
error: function(jqXHR){
alert("发生错误:" + jqXHR.status);
},
});
});
});
</script>
处理跨域方式
一个域名地址的组成 : http://www.abc.com:8080/script/jquery.js
http://
协议
www
子域名
abc.com
主域名
8080
端口号
script
请求资源地址
当协议、子域名、主域名、端口号中任意一个不相同,都算不同域
不同域之间互相请求资源,都算”跨域”
跨域
JavaScript 处于安全的考虑,不允许跨域调用其他页面的对象,比如 a.com 域名下的 js 无法操作 b.com 或者是 c.a.com 域名下的对象。
处理跨域的方式 一 — 代理
通过在同域名的 web服务器端创建一个代理:
北京服务器(域名 : www.beijing.com)
上海服务器(域名 : www.shanghai.com)
比如在北京的 web服务器的后台 (www.beijing.com/proxy-shanghaiservice.php) 来调用上海的服务器 (www.shanghai.com/service.php) 的服务,然后把响应结果返回给前端,这样前端就调用北京同域名的服务和调用上海服务效果一样了
处理跨域的方式 二 — JSONP
JSONP 可用于解决主流浏览器的跨域数据访问的问题
// 在 www.aaa.com 页面中
<script>
function jsonp(json){
alert(json(["name"]));
}
</script>
<script src="http://www.bbb.com/jsonp.js"></script>
// 在 www.bbb.com 页面中
jsonp({"name" : "Lyf", "age" : "20"});
jQuery 的 $.ajax()
本身就支持 JSONP 的处理方式
JSONP 只支持 GET 请求,而且 JSONP 返回的是一个数组
使用 JSONP 改造刚才的例子
<script>
$(document).ready(function(){
$("#search").click(function(){
$.ajax({
type: "GET",
url: "http://127.0.0.1:8080/ajaxdemo/serverjson2.php?number=" + $("#keyword").val(),
// 这里把 json 改为 jsonp
dataType: "jsonp",
// 增加一个 jsonp 的属性, 值可以随意命名
jsonp : "callback",
success: function(data) {
if (data.success) {
$("#searchResult").html(data.msg);
} else {
$("#searchResult").html("出现错误:" + data.msg);
}
},
error: function(jqXHR){
alert("发生错误:" + jqXHR.status);
},
});
});
});
</script>
后端也要将相应的 jsonp 获取
<?php
//设置页面内容是html编码格式是utf-8
//header("Content-Type: text/plain;charset=utf-8");
header("Content-Type: application/json;charset=utf-8");
//header("Content-Type: text/xml;charset=utf-8");
//header("Content-Type: text/html;charset=utf-8");
//header("Content-Type: application/javascript;charset=utf-8");
//定义一个多维数组,包含员工的信息,每条员工信息为一个数组
$staff = array
(
array("name" => "洪七", "number" => "101", "sex" => "男", "job" => "总经理"),
array("name" => "郭靖", "number" => "102", "sex" => "男", "job" => "开发工程师"),
array("name" => "黄蓉", "number" => "103", "sex" => "女", "job" => "产品经理")
);
//判断如果是get请求,则进行搜索;如果是POST请求,则进行新建
//$_SERVER是一个超全局变量,在一个脚本的全部作用域中都可用,不用使用global关键字
//$_SERVER["REQUEST_METHOD"]返回访问页面使用的请求方法
if ($_SERVER["REQUEST_METHOD"] == "GET") {
search();
} elseif ($_SERVER["REQUEST_METHOD"] == "POST"){
create();
}
//通过员工编号搜索员工
function search(){
// 这里获取前端的 jsonp 的值
$jsonp = $_GET["callback"];
//检查是否有员工编号的参数
//isset检测变量是否设置;empty判断值为否为空
//超全局变量 $_GET 和 $_POST 用于收集表单数据
if (!isset($_GET["number"]) || empty($_GET["number"])) {
// 返回 jsonp 的值
echo $jsonp . '({"success":false,"msg":"参数错误"})';
return;
}
//函数之外声明的变量拥有 Global 作用域,只能在函数以外进行访问。
//global 关键词用于访问函数内的全局变量
global $staff;
//获取number参数
$number = $_GET["number"];
$result = $jsonp . '({"success":false,"msg":"没有找到员工。"})';
//遍历$staff多维数组,查找key值为number的员工是否存在,如果存在,则修改返回结果
foreach ($staff as $value) {
if ($value["number"] == $number) {
$result = $jsonp . '({"success":true,"msg":"找到员工:员工编号:' . $value["number"] .
',员工姓名:' . $value["name"] .
',员工性别:' . $value["sex"] .
',员工职位:' . $value["job"] . '"})';
break;
}
}
echo $result;
}
//创建员工
function create(){
//判断信息是否填写完全
if (!isset($_POST["name"]) || empty($_POST["name"])
|| !isset($_POST["number"]) || empty($_POST["number"])
|| !isset($_POST["sex"]) || empty($_POST["sex"])
|| !isset($_POST["job"]) || empty($_POST["job"])) {
echo '{"success":false,"msg":"参数错误,员工信息填写不全"}';
return;
}
//TODO: 获取POST表单数据并保存到数据库
//提示保存成功
echo '{"success":true,"msg":"员工:' . $_POST["name"] . ' 信息保存成功!"}';
}
?>