導讀:
JAVA---一路上有你 blue
我喜歡在鍵盤上飛奔的感覺盡量讓自己的每一行代碼都很漂亮
49 隨筆 :: 22 文章 :: 95 評論 :: 0 Trackbacks
這二天用prototype.js中的ajax.request做了些東西,閑時看了下源碼,體會如下:
在用AJAX部分前,有如下一些函數得瞭解一下:
Class變數
var?Class?=?{
create:?function()?{
return?function()?{
this.initialize.apply(this,?arguments);
}??}}
initialize相當於構造器,和java的構造器一樣,可以自訂為帶參數性質的。prototype中很多個物件都是用它來建立的,ajax也不例外。
Try.these() 方法
var?Try?=?{
these:?function()?{
var?returnValue;
for?(var?i?=?0?i?
var?lambda?=?arguments[i];
try?{
returnValue?=?lambda();
break??????}?catch?(e)?{}????}????return?returnValue;
}}
它使得實現當你想調用不同的方法直到其中的一個成功正常的這種需求變得非常容易, 他把一系列的方法作為參數並且按順序的一個一個的執行這些方法直到其中的一個成功執行,返回成功執行的那個方法的傳回值。
ajax就是通過它得到一個可以跨borswer的xmlhttp的:
var?Ajax?=?{
getTransport:?function()?{
return?Try.these(
function()?{return?new?ActiveXObject('Msxml2.XMLHTTP')},
function()?{return?new?ActiveXObject('Microsoft.XMLHTTP')},
function()?{return?new?XMLHttpRequest()}????)?||?false??}??activeRequestCount:?0}
Object.extend方法:
Object.extend?=?function(destination,?source)?{
for?(property?in?source)?{
destination[property]?=?source[property];
}??return?destination;
}
顧名思義,可正擴充了一個對象屬性列表。這樣說可能不太明白,結合Ajax再下就清楚了,如下,
Ajax.Base.prototype?=?{
setOptions:?function(options)?{
this.options?=?{
method:???????'post',
asynchronous:?true,
parameters:???'
}????Object.extend(this.options,?options?||?{});
},
}
可以看到在prototype中用ajax的時候,它的options預設有三個,預設值如上所示。這裡可以通過以下方式來改變其默值(Ajax.Request的用法,呆會兒再看):
var?pars?=?'method=update&mbid=917';var?my?=?new?Ajax.Request(
uri,?
{
method:?'post',
parameters:?pars,
asynchronous:?false,
});
}
這時有個問題可能不太好處理,假如想增加其它參數,怎麼知道我所增加的參數是否符合prototype呢?確實!比如我想通過send方法傳一段資料到後台,該用什麼參數呢?在prototype中有如下代碼:
var?body?=?this.options.postBody???this.options.postBody?:?parameters;this.transport.send(this.options.method?==?'post'???body?:?null);
可以看到應該是postBody,對於prototype中的參數以及其所代表的意義我想還是得通過源檔案一個個的找。作者並沒有初始一個集合(廢話,不然也不要Object.extend方法了)。我覺得這個地方有待改進... ...
在send時方法一定要用post才會生效,這個時候parameters就會失效了,源碼如下:
if?(this.options.method?==?'get'?&&?parameters.length?>?0)
this.url?+=?(this.url.match(//?/)???'&'?:?'?')?+?parameters;
所以假如後台一定要一個parameter的話,比如若用到Struts的LookupDispatchAction就很可能要一個method參數。這時應該直接放到uri中去,最後要注意的一點就是用post的時候,一定要將回應標頭設定成Content-type==application/x-www-form-urlencoded. 好在prototype已經考慮到了這點:
this.setRequestHeaders();//其具體代碼可以看源檔案var?body?=?this.options.postBody???this.options.postBody?:?parameters;this.transport.send(this.options.method?==?'post'???body?:?null);
在這兒我說一下我在使用ajax過程中遇到亂碼的解決方案:
從C到S頭端時,在S端接到的是亂碼解決分析過程。首先要明白AJAX內部是以utf-8來編碼傳輸資料的。我們在頁面所看到的資料都是按照我們自己預定的字元集解碼所得到的。OK,現在假設我們在S端收到了來自C端的DATA為亂碼,在C端(不管你的WEB頁面是用什麼編碼方式)AJAX在其傳輸中把所傳輸的資料解碼成UTF-8格式,到了S端後,我可能對所有請求方式都過濾編碼,比如有如下設定:
encodingFilter?????com.CharacterEncodingFilter
???encoding???GBK????
所以我們在S端看到的是將以UTF-8編碼過的資料再以GBK解碼後所得到的資料,這樣亂碼就出來了。所以解決也很簡單,交其重新以自己的方式編碼就OK了
new String(str.getBytes("gbk"),"utf-8");
同樣的道理,假如在C端碰到的是亂碼,那麼在S端返回資料前將資料以UTF-8的格式傳輸
src.getBytes("UTF-8")
ajax.request中對事件的響應:
首先我們得在請求初始化中加入響應狀態與自訂函數:
var?my?=?new?Ajax.Request(
url,?
{
method:?'get',
parameters:?pars,
asynchronous:?true,
onComplete:?showResponse
});
它初始化了一個ajax事件的集合
Ajax.Request.Events?=??['Uninitialized',?'Loading',?'Loaded',?'Interactive',?'Complete'];
這五個狀態正好對應五個readystate,ajax的五個readystate分別如下:
0 (未初始化) 對象已建立,但是尚未初始化(尚未調用open方法)
1 (初始化) 對象已建立,尚未調用send方法
2 (發送資料) send方法已調用,但是當前的狀態及http頭未知
3 (資料傳送中) 已接收部分資料,因為響應及http頭不全,這時通過responseBody和responseText擷取部分資料會出現錯誤,
4 (完成) 資料接收完畢,此時可以通過通過responseBody和responseText擷取完整的回應資料
然後根據status(點這兒可以下載查看ajax參考資料,查看其所有屬性)來觸發指定事件,觸發代碼:
onStateChange:?function()?{
var?readyState?=?this.transport.readyState;
if?(readyState?!=?1)
this.respondToReadyState(this.transport.readyState);
}?respondToReadyState:?function(readyState)?{
var?event?=?Ajax.Request.Events[readyState];
再次可以看到正好事件集合與readyState正好對應來調用,而通過以下來調用WEB自訂函數showResponse()
try?{
(this.options['on'?+?event]?||?Prototype.emptyFunction)(transport,?json);
Ajax.Responders.dispatch('on'?+?event,?this,?transport,?json);
}?catch?(e)?{
this.dispatchException(e);
}
未完,待續...