AJAX全稱爲“Asynchronous JavaScript and XML”(非同步JavaScript和XML),是一種創建互動式網頁應用的網頁開發技術。使用Ajax的最大優點,就是能在不更新整個頁面的前提下維護數據。這使得Web應用程序更爲迅捷地迴應用戶動作,並避免了在網絡上發送那些沒有改變過的信息。Ajax不需要任何瀏覽器插件,但需要用戶允許JavaScript在瀏覽器上執行。就像DHTML應用程序那樣,Ajax應用程序必須在衆多不同的瀏覽器和平臺上經過嚴格的測試。隨着Ajax的成熟,一些簡化Ajax使用方法的程序庫也相繼問世。同樣,也出現了另一種輔助程序設計的技術,爲那些不支持JavaScript的用戶提供替代功能。
所謂核心代碼就是提供一個能夠跨瀏覽器的Ajax調用代碼,這部分代碼是後面擴展代碼的必備部分,在這部分代碼中我們提供了一個創建XMLHttpRequest對象並能夠與Web服務器進行異步數據交換。在我寫的這些代碼中,自定義了兩個相關的函數,一個是通用的獲取HTML對象函數,還有一個就是自動過濾字符串開頭結尾的空格,代碼如下:function $( elementId ) {
return document.getElementById(elementId);
}
function trim(str){ //刪除左右兩端的空格
return str.replace(/(^\s*)|(\s*$)/g, "");
}Ajax的核心代碼如下:/*
* 根據不同的瀏覽器,獲取Ajax對象
*/
function getAjaxObject() {
var xmlHttpRequest;
// 判斷是否把XMLHttpRequest實現爲一個本地javascript對象
if(window.XMLHttpRequest){
xmlHttpRequest = new XMLHttpRequest();
}else if(window.ActiveXObject){ // 判斷是否支持ActiveX控件
try{
// 通過實例化ActiveXObject的一個新實例來創建XMLHttpRequest對象
xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP"); // msxml3以上版本
}catch(e){
try{
// 通過實例化ActiveXObject的一個新實例來創建XMLHttpRequest對象
xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP"); // msxml3以下版本
}catch(e){}
}
}
if ( !xmlHttpRequest ) {
alert("創建Ajax對象失敗,您將無法正常瀏覽網頁");
}
return xmlHttpRequest;
}
/*
* 異步方式提交請求
*/
function sendRequestByAjax(method, url, data, dataHandler) {
// 獲取Ajax對象
request = getAjaxObject();
// 設置回調函數
if( !IE4 ){
request.onload = dataHandler;
} else {
request.onreadystatechange = dataHandler;
}
request.open(method, url, true); // true代表使用異步方式 false代表使用同步方式
// 處理提交方式
if ( "get" == method.toLowerCase() ) {
// 使用GET方式提交數據
var urls = url.split("?");
if ( urls[1] == "" || typeof(urls[1]) == "undefined" ) {
url = urls[0] + "?" + data;
} else {
url = urls[0] + "?" + urls[1] + "&" + data;
}
data = null; // for GET method,request必須爲空
} else if ( "post" == method.toLowerCase() ){
// 使用POST方式提交數據
request.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
request.send(data);
}
根據Ajax提出者Jesse James Garrett建議,Ajax使用XHTML+CSS來表示信息,使用JavaScript操作DOM(Document Object Model)進行動態顯示及交互,使用XML和XSLT進行數據交換及相關操作,由於Opera瀏覽器不支持XSLT格式對象,也不支持XSLT,所以現在一般情況下都是使用XML進行數據傳遞。在回調函數中,會出現request的一些相關屬性,其代表值如下:readyState:提供當前 HTML 的就緒狀態。
0:請求未初始化
1:請求已經建立,但是還沒有發送(還沒有調用 send())
2:請求已發送,正在處理中(通常現在可以從響應中獲取內容頭)
3:請求在處理中,通常響應中已有部分數據可用了
4:響應已完成
status:提供當前HTML的狀態碼
401:未經授權
403:禁止訪問
404:沒找到訪問頁
200:正常回調函數如下所示:/*
* 返回數據格式爲XML的回調函數
*/
function xmlCallBack() {
// 數據接收完成
if( request.readyState == 4 ){
// 數據正常接收
if( request.status == 200 ){
// 調用XML文件解析函數
parseXMLMessage();
} else {
// 顯示錯誤信息
alert("Not able to retrieve description"+request.statusText);
}
}
}
/*
* XML文件解析函數
*/
function parseXMLMessage() {
// 獲取返回的XML文件
var xmlDoc=request.responseXML.documentElement;
// 解析XML文件
parseXML("elementId", xmlDoc);
}
/*
* 解析XML文件
* @param elementId 要將數據綁定的對象Id
* @param xmlDoc 要解析的XML文件
*/
function parseXML(elementId, xmlDoc) {// 這裏XML文件的格式根據你的自定義,自行修改
var xmlRoot = xmlDoc.getElementsByTagName("items");
var dataType = xmlRoot[0].getAttribute("dataType");
var items = xmlDoc.getElementsByTagName('item');
switch ( dataType.toLowerCase() ) {
case "array" :
// 返回對象爲結果集
bindItems(elementId, items);
break;
case "string" :
// 返回對象爲字符串
bindText(elementId, items[0].childNodes[0].firstChild.nodeValue);
}
}如果Ajax調用後返回的是一個HTML頁面,則可以使用下面的這個回調函數:/*
* HTML文件解析函數
*/
function htmlCallBack() {
if( request.readyState == 4 ){
if( request.status == 200 ){
parseHTMLMessage();
} else {
alert("Not able to retrieve description"+request.statusText);
}
}
}
/*
* 解析HTML文件
*/
function parseHTMLMessage() {
// 獲取返回的HTML代碼
var htmlCode = request.responseText;
// 綁定HTML代碼
bindText("elementId", htmlCode);
}
數據綁定根據不同的控件類型,可以使用以下兩個數據綁定函數,能夠實現綁定select控件、ul無序列表、插入HTML代碼等:/*
* 綁定結果集
*/
function bindItems(elementId, items) {
var elem = $(elementId);
// 判斷要綁定的對象,類型是否匹配
if ( elem.tagName.toLowerCase() != "select" && elem.tagName.toLowerCase() != "ul" ) {
alert("數據類型不匹配,無法進行數據綁定");
return;
}
// 綁定select
if ( elem.tagName.toLowerCase() == "select" ) {
while ( elem.childNodes.length > 0 ) {
// 清除現有數據
elem.removeChild(elem.childNodes[0]);
}
// 綁定數據
for ( var i = 0; i < items.length; i++ ) {
var option = document.createElement("OPTION");
var Data = items[i];
option.value = Data.childNodes[0].firstChild.nodeValue;
option.text = Data.childNodes[1].firstChild.nodeValue;
elem.options.add(option);
}
} else if ( elem.tagName.toLowerCase() == "ul" ) {
// 綁定ul列表
elem.innerHTML = "";
// bind data
for ( var i = 0; i < items.length; i++ ) {
var Data = items[i];
var urlAddress = Data.childNodes[0].firstChild.nodeValue;
var showText = Data.childNodes[1].firstChild.nodeValue;
var innerCode = "<li><a href=\"" + urlAddress + "\" title=\"" + showText + "\">" + showText + "</a></li>";
elem.innerHTML += innerCode;
}
}
}
/*
* 綁定字符串,也可以實現綁定HTML代碼
*/
function bindText(elementId, value) {
var elem = $(elementId);
// 分析綁定對象類型
switch ( elem.tagName.toLowerCase() ) {
case "div":
case "span":
case "textarea":
elem.innerHTML = value;
break;
case "input":
elem.value = value;
break;
default:
alert("數據類型不匹配,無法進行數據綁定");
return;
}
saveHistory(elementId); // 保存歷史記錄用於實現瀏覽器的前進、後退按鈕
}
通過Ajax提交Form有以下兩個非常重要的地方:1、需要解析所有Form中的控件,將控件拼成類似於“?param1=value1¶m2=value2......”這樣的字符串,然後通過“POST”模式異步提交,將上面拼成的字符串通過request.send(data)發送到服務器。2、關於文件上傳,由於我沒有這方面的需求,沒有寫出一個測試後的代碼,但通過查閱相關資料,看到可以通過隱藏IFrame來實現這一功能。通過Ajax異步提交表單的代碼如下:/*
* 通過Ajax異步提交表單
*/
function submitFormByAjax(formId) {
sendRequestByAjax($(formId).method, $(formId).getAttributeNode("action").value, encodeFormData($(formId)), htmlCallBack);
}解析Form內控件,並拼成字符串的函數如下:/*
* 分析Form表單數據
* @param formElement Form對象
*/
function encodeFormData(formElement) {
var whereClause = "";
var and = "";
for ( i = 0 ; i < formElement.length ; i++ ) {
var element = formElement[i];
if ( element.name != "" ) {
if (element.type=='select-one') {
element_value = element.options[element.selectedIndex].value;
} else if ( element.type == 'checkbox' || element.type == 'radio' ) {
if ( element.checked == false ) {
break;
}
element_value = trim(element.value);
} else {
element_value = trim(element.value);
}
whereClause += and + trim(element.name) + '=' + element_value.replace(/\&/g,"%26");
and = "&"
}
}
return whereClause;
}
很多人在使用了Ajax技術後會發現,瀏覽器的前進、後退按鈕無效了,大大降低了用戶體驗,曾經這一點也被作爲Ajax技術的弊端而大範圍討論,後來經過不斷的嘗試,終於實現了這一功能,聽起來很簡答,就是通過一個隱藏的IFrame,使用JavaScript改變IFrame的src屬性而激活瀏覽器的前進、後退按鈕。再通過一個特殊的JavaScript函數,實現更新頁面數據。具體的代碼如下:var historyValue = new Array(10); // 保存記錄的最大次數
var historyCount = 0;
/*
* 保存歷史記錄
* @param elementId 要保存的區域ID
*/
function saveHistory(elementId) {
// "historyFrame"隱藏的IFrame的ID屬性值
var iframeDocument = $("historyFrame");
if ( iframeDocument != null ) {
if ( historyCount == 9 ) {
historyCount = 0;
} else {
historyCount++;
}
historyValue[historyCount] = new Array(2);
historyValue[historyCount][0] = elementId;
var element = $(elementId);
historyValue[historyCount][1] = element.innerHTML;
iframeDocument.src = "/history.jsp?" + historyCount;
}
}
/*
* 獲取歷史記錄
* @param historyIndex 歷史記錄索引號
*/
function getHistory(historyIndex) {
if ( historyIndex != historyCount ) {
if ( historyValue[historyIndex] ) {
historyCount = historyIndex;
}
var element = $(historyValue[historyCount][0]);
element.innerHTML = historyValue[historyCount][1];
}
}history.jsp頁面中的代碼很簡單,只有以下代碼:<script>
var url=window.location.href;
if(url.indexOf('?')>-1)
{
parent.getHistory(url.substr(url.indexOf('?')+1));
document.write(window.location.search.substr(1));
}
</script>在頁面最下端記得寫上下面的代碼:<iframe id="historyFrame" name="historyFrame" src="/history.jsp?0" height="0px" frameborder="no"></iframe>
下面是java中生成xml的方法:
PrintWriter out = response.getWriter();
StringBuffer buffer = new StringBuffer();
out.println("<?xml version=\"1.0\" encoding=\"gbk\"?>");
for (int i = 0; i < 10; i++) {
buffer.append("\n\t<children>");
buffer.append("\n\t\t<id>").append(1)
.append("</id>");
buffer.append("\n\t\t<name>").append(2)
.append("</name>");
buffer.append("\n\t</children>");
}
out.println(buffer.toString());