1. 程式人生 > >JQuery學習筆記——Ajax全接觸:Ajax語法,JSON ,跨域等問題

JQuery學習筆記——Ajax全接觸:Ajax語法,JSON ,跨域等問題

1、$("div").ajax();

$(document).ready(function(){
  $("#b01").click(function(){
      htmlobj=$.ajax({url:"/jquery/test1.txt",async:false});
      $("#myDiv").html(htmlobj.responseText);
  });
});

2、JSON與XML對比

· json的長度和xml格式比起來很短小
· json讀寫速度更快
· json可以使用JavaScript內建的方法直接進行解析,轉換成JavaScript物件,非常方便
 (所以使用Ajax時基本上都採用json傳遞資料,很少使用XML)

3、JSON的語法規則

· JSON資料的書寫格式是:名稱、值對
    
    名稱/值對組合中的名稱寫在前面(在雙引號中),值對寫在後面(同樣在雙引號中),中間用冒號隔開:比如 "name":"郭靖"
· JSON的值可以是下面這些型別
    
    數字(整數或者浮點數),比如 123,1.23
    字串(在雙引號中)
    邏輯值(true或false)
    陣列(在方括號中)
    物件(在花括號中)
    null
· JSON語法規則示例
    {
        "staff":[
            {"name":"洪七","age":70},
            {"name":"郭靖","age":35}, 
            {"name":"黃蓉","age":30}
        ]
    } 

4、JSON解析

· eval和JSON.parse
· 在程式碼中使用eval函式是非常危險的!特別是用它執行第三方的JSON資料(其中可能包含有惡意程式碼)時,儘可能使用JSON.parse()方法解析字串本身,該方法還可以捕捉JSON中的語法錯誤
示例

· eval方法
    var jsondata = '{"staff":[{"name":"洪七","age":70},{"name":"郭靖","age":35},{"name":"黃    蓉","age":30}]}'; 
    var jsonobj = eval('('+jsondata+')');alert(jsonobj.staff[0].name);
· parse方法
    var jsondata = '{"staff":[{"name":"洪七","age":70},{"name":"郭靖","age":35},{"name":"黃蓉","age":30}]}'; 
    var jsonobj = JSON.parse(jsondata);alert(jsonobj.staff[0].name);

區別:
· eval方法:不看字串是否合法,還會解析字串中的方法
    var jsondata = '{"staff":[{"name":"洪七","age":alert(123)},{"name":"郭靖","age":35},{"name":"黃    蓉","age":30}]}'; 
    var jsonobj = eval('('+jsondata+')');alert(jsonobj.staff[0].name);
//函式會先彈出123,再彈出洪七
· JSON.parse()方法:若字串中有方法,會丟擲錯誤
    var jsondata = '{"staff":[{"name":"洪七","age":alert(123)},{"name":"郭靖","age":35},{"name":"黃蓉","age":30}]}'; 
    var jsonobj = JSON.parse(jsondata);alert(jsonobj.staff[0].name);

5、JSON字串格式化和校驗工具:JSONLint

6、Ajax原生JS實戰程式碼

        客戶端

<!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>
document.getElementById("search").onclick = function() { 
	var request = new XMLHttpRequest();
	request.open("GET", "server.php?number=" + document.getElementById("keyword").value);
	request.send();
	//獲取伺服器上readystate屬性的改變,當他變為4的話說明請求結束
	request.onreadystatechange = function(){
		if(request.readyState === 4){
			if(request.status === 200){
				document.getElementById("searchResult").innerHTML = request.response
			}else{alert("發生錯誤"+request.status)};
		}
	}
}

document.getElementById("save").onclick = function() { 
	var request = new XMLHttpRequest();
	request.open("POST", "server.php");
	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);
	//獲取伺服器上readystate屬性的改變,當他變為4的話說明請求結束
	request.onreadystatechange = function(){
		if(request.readyState === 4){
			if(request.status === 200){
				document.getElementById("createResult").innerHTML = request.response
			}else{alert("發生錯誤"+request.status)};
		}
	}
}

{"staff":[{"name":"洪七","age":70},{"name":"郭靖","age":35},{"name":"黃蓉","age":30}]}
	
	
</script>
</body>
</html>

伺服器端

<?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"] . " 資訊儲存成功!";
}

7、Ajax+json使用原生JS實戰程式碼

客戶端

<!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>
document.getElementById("search").onclick = function() { 
	//傳送Ajax查詢請求並處理
	var request = new XMLHttpRequest();
	request.open("GET", "service.php?number=" + document.getElementById("keyword").value);
	request.send();
	//獲取伺服器上readystate屬性的改變,當他變為4的話說明請求結束
	request.onreadystatechange = function(){
		if(request.readyState === 4){
			if(request.status === 200){
				var data = JSON.parse(request.responseText);
				if(data.success){
					document.getElementById("searchResult").innerHTML = data.msg;
				}else{
					document.getElementById("searchResult").innerHTML = "出現錯誤:"+data.msg;
				}
			}else{alert("發生錯誤"+request.status)};
		}
	}
}

document.getElementById("save").onclick = function() { 
	//傳送Ajax建立請求並處理
	var request = new XMLHttpRequest();
	request.open("POST", "service.php");
	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);
	//獲取伺服器上readystate屬性的改變,當他變為4的話說明請求結束
	request.onreadystatechange = function(){
		if(request.readyState === 4){
			if(request.status === 200){
				var data = JSON.parse(request.responseText);
				if(data.success){
					document.getElementById("createResult").innerHTML = data.msg;
				}else{
					document.getElementById("createResult").innerHTML = "出現錯誤:"+data.msg;
				}
			}else{alert("發生錯誤:"+request.status)};
		}
	}
}

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

伺服器端

<?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 '{"success":false,"msg":"引數錯誤"}';
		return;
	}
	//函式之外宣告的變數擁有 Global 作用域,只能在函式以外進行訪問。
	//global 關鍵詞用於訪問函式內的全域性變數
	global $staff;
	//獲取number引數
	$number = $_GET["number"];
	$result = '{"success":false,"msg":"沒有找到員工"}';
	
	//遍歷$staff多維陣列,查詢key值為number的員工是否存在,如果存在,則修改返回結果
	foreach ($staff as $value) {
		if ($value["number"] == $number) {
			$result ='{"success":true,"msg":
					"找到員工:員工編號:'.$value["number"].',員工姓名:'.$value["name"].
					',員工性別:'.$value["sex"].
					',員工職位:' . $value["job"].'"}';
			//$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表單資料並儲存到資料庫
	
	//提示儲存成功
	echo '{"success":true,"msg":"員工:'.$_POST["name"].'資訊儲存成功!"}';
}

8、用jQuery實現Ajax

· jQuery.ajax([settings])

·    type:型別,"POST"或"GET",預設為"GET"
·    url:傳送請求的地址
·    data:是一個物件,連同請求一起傳送到伺服器
·    dataType:預期伺服器返回的資料型別。如果不指定,jQuery將自動根據HTTP包MIME資訊來智慧判斷,一般我們採用json格式,可以設定為"json"
·    success:是一個方法,請求成功後的回撥函式。傳入返回後的資料,以及包含成功程式碼的字串
·    error:是一個方法,請求失敗後呼叫此函式。傳入XMLHttpRequest物件

客戶端示例程式碼

<!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>
	<script src="http://apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js"></script>
</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).ready(function(){
	$("#search").click(function(){
		$.ajax({
			type:"GET",
			url:"service.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)
			}
			
		})
	})	
})
//POST請求
$(document).ready(function(){
	$("#save").click(function(){
		$.ajax({
			type:"POST",
			url:"service.php",
			dataType:"json",
			data:{
				name:$("#staffName").val(),
				number:$("#staffNumber").val(),
				sex:$("#staffSex").val(),
				job:$("#staffJob").val(),
			},
			success:function(data){
				if(data.success){
					$("#searchResult").html(data.msg);
				}else{
					$("#searchResult").html("出現錯誤:"+data.msg);
				}
			},
			error:function(jqXHR){
				alert("發生錯誤"+jqXHR.status)
			}
			
		})
	})	
})

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

伺服器端全部程式碼

<?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 '{"success":false,"msg":"引數錯誤"}';
		return;
	}
	//函式之外宣告的變數擁有 Global 作用域,只能在函式以外進行訪問。
	//global 關鍵詞用於訪問函式內的全域性變數
	global $staff;
	//獲取number引數
	$number = $_GET["number"];
	$result = '{"success":false,"msg":"沒有找到員工"}';
	
	//遍歷$staff多維陣列,查詢key值為number的員工是否存在,如果存在,則修改返回結果
	foreach ($staff as $value) {
		if ($value["number"] == $number) {
			$result ='{"success":true,"msg":
					"找到員工:員工編號:'.$value["number"].',員工姓名:'.$value["name"].
					',員工性別:'.$value["sex"].
					',員工職位:' . $value["job"].'"}';
			//$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表單資料並儲存到資料庫
	
	//提示儲存成功
	echo '{"success":true,"msg":"員工:'.$_POST["name"].'資訊儲存成功!"}';
}

9、跨域問題

·    當協議,子域名,主域名,埠號中任意一個不相同時,都算作不同域
·    不同域之間互相請求資源,就算做跨域
     比如:http:www.abc.con/index.html 請求 http://www.efg.com/service.php

跨域

·    JavaScript出於安全方面的考慮,不允許跨域呼叫其他頁面的物件。什麼是跨域呢?簡單的理解就是因為JavaScript同源策略的限制,a.com域名下js無法操作b.com或者是c.a.com域名下的物件

示例

·    www.abc.com/index.html呼叫www.abc.com/service.php (非跨域)
·    www.abc.com/index.html呼叫www.efg.com/service.php (跨域)
·    www.abc.com/index.html呼叫www.abc.com/service.php (跨域)
·    www.abc.com/index.html呼叫bbb.abc.com:81/service.php (跨域)
·    www.abc.com/index.html呼叫https://www.abc.com/service.php (跨域)

9.1 處理跨域方法一——代理

·    通過在同域名的web伺服器端建立了一個代理:
·    北京伺服器(域名為:www.beijing.com)
     上海伺服器(域名為:www.shanghai.com)
·    比如在北京的web伺服器後臺(www.beijing.com/proxy-shanghaiservice.php)來
     呼叫上海的伺服器的(www.shanghai.com/service.php)的服務,
     然後將響應結果傳遞給前端,這樣前端呼叫北京同域名的服務和呼叫上海的服務效果相同

9.2  處理跨域方法二——JSONP——主要用於解決主流瀏覽器的跨域資料訪問的問題(只支援GET請求)

在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':'洪七','age':24});

客戶端程式碼改造(JQ)

$(document).ready(function(){
	$("#search").click(function(){
		$.ajax({
			type:"GET",
			url:"http://127.0.0.1:8080/ajaxdemo/jqservice.php?number=" + $("#keyword").val(),
			dataType:"jsonp",   //dataType 由json修改為jsonp
			jsonp:'callback',    //新增jsonp屬性,"callback為函式名"
			success:function(data){
				if(data.success){
					$("#searchResult").html(data.msg);
				}else{
					$("#searchResult").html("出現錯誤:"+data.msg);
				}
			},
			error:function(jqXHR){
				alert("發生錯誤"+jqXHR.status)
			}
			
		})
	})	
})

伺服器端程式碼改造

function search(){
	$jsonp=$_GET["callback"];   //在函式中增加該語句
	//檢查是否有員工編號的引數
	//isset檢測變數是否設定;empty判斷值為否為空
	//超全域性變數 $_GET 和 $_POST 用於收集表單資料
	if (!isset($_GET["number"]) || empty($_GET["number"])) {
		echo '{"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"].'"})';
			//$result = '{"success":true,"msg":
//					"找到員工:員工編號:' . $value["number"] . 
//							',員工姓名:' . $value["name"] . 
//							',員工性別:' . $value["sex"] . 
//							',員工職位:' . $value["job"] . '"}';
			break;
		}
	}
    echo $result;
}

9.3  處理跨域方法三——XHR2

·    HTML5提供的XMLHttpRequest Levels已經實現了跨域訪問以及一些其他的新功能
·    IE10以下的版本都不支援(所以如果忽略IE可以使用該方法)
·    在伺服器端做一些小小的改造即可
     header('Access-Control-Allow-Origin:*');
     header('Access-Control-Allow-Methods:POST,GET');

程式碼改動

//客戶端不需要任何的改動
//伺服器端在頭部加上下面兩行程式碼即可
     header('Access-Control-Allow-Origin:*');
     header('Access-Control-Allow-Methods:POST,GET');