這二天用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?
<
?arguments.length;?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端后,我可能對所有請求方式都過濾編碼,比如有如下設置:
<
filter
>
??
<
filter-name
>
encodingFilter
</
filter-name
>
??
<
filter-class
>
???com.CharacterEncodingFilter
??
</
filter-class
>
??
<
init-param
>
???
<
param-name
>
encoding
</
param-name
>
???
<
param-value
>
GBK
</
param-value
>
??
</
init-param
>
??
?
</
filter
>
所以我們在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);
????}
?未完,待續...