|
Posted on 2008-04-07 11:00 oathleo 閱讀(1582) 評論(1) 編輯 收藏 所屬分類: Web
Ext是一個非常好的Ajax框架,其華麗的外觀表現確實令我們折服,然而一個應用始終離開不服務器端,因此在實現開發中我們需要對Ext與服務器端的交互技術有較為詳細的了解,在開發中才能游刃有余地應用。本文對Ext應用中與服務器交互的常用方法作具體的介紹,本文的內容大部份來源于《ExtJS實用開發指南》。 總體來說,Ext與服務器端的交互應用可以歸結為三種類型,包含表單FormPanel的處理(提交、加載)、控件交互及用戶發起的Ajax請求等三種。 一、表單提交(submit)及加載(load) 這里說的表單是指用Ext的FormPanel建立的表單,看下面的例子:
Ext.onReady(
function
()
...
{
 ??
var
?f
=
new
?Ext.form.FormPanel(
...
{
??renderTo:
"
hello
"
,
??title:
"
用戶信息錄入框
"
,
??height:
200
,
??width:
300
,
??labelWidth:
60
,
??labelAlign:
"
right
"
,
??frame:
true
,
 ??defaults:
...
{xtype:
"
textfield
"
,width:
180
}
,
??items:[
 ??
...
{name:
"
username
"
,fieldLabel:
"
姓名
"
}
,
 ??
...
{name:
"
password
"
,fieldLabel:
"
密碼
"
,inputType:
"
password
"
}
,
 ??
...
{name:
"
email
"
,fieldLabel:
"
電子郵件
"
}
,
 ??
...
{xtype:
"
textarea
"
,name:
"
intro
"
,fieldLabel:
"
簡介
"
}
??],
 ??buttons:[
...
{text:
"
提交
"
}
,
...
{text:
"
取消
"
}
]??
?}
)
?}
);
?
要提交該表單,則可以直接調用FormPanel下面form對象的submit方法即可,代碼如下:
f.form.submit(
...
{
?????url:
"
server.js
"
,
waitTitle:
"
請稍候
"
,
?????waitMsg:
"
正在提交表單數據,請稍候。。。。。。
"
?????}
);
調用submit方法后,默認情況下服務器端應用程序需要返回一個JSON數據對象,該對象包含兩個屬性,success的值是布爾值true或false,如果success的值為true,則表示服務器端處理成功,否則表示失敗;而errors的值是一個對象,對象中的每一個屬性表示錯誤的字段名稱,而屬性值為錯誤描述。 比如,如果我們有服務器端驗證,下面的返回結果表示當表單提交處理出錯時給客戶端返回的數據。 server.js文件中的內容如下:
...
{
????success:?
false
,
 ????errors:?
...
{
????????username:?
"
姓名不能為空
"
,
????????times:?
"
遲到次數必須為數字!
"
????}
}
結果如圖所示:
? 當然,如果success屬性值改為true,則表示服務器端的處理成功,此時可以在success定義的回調函數中作相應的處理,比如下面的代碼表示在表單處理成功后,彈出提示信息,代碼如下:
?
...
{
????success:?
true
,
 ????data:?
...
{
????????username:?
"
冷雨
"
,
????????times:?
1
????}
}
下面我們看一個使用到表單數據加載的簡單示例代碼:
Ext.QuickTips.init();
 Ext.onReady(
function
()
...
{?
 ?
var
?f
=
new
?Ext.form.FormPanel(
...
{
??renderTo:
"
hello
"
,
??title:
"
用戶信息錄入框
"
,
??height:
130
,
??width:
320
,
??labelWidth:
60
,
??labelAlign:
"
right
"
,
??frame:
true
,
 ??defaults:
...
{width:
180
,xtype:
"
textfield
"
}
,
 ??items:[
...
{
???xtype:
"
textfield
"
,
???name:
"
username
"
,
???fieldLabel:
"
姓名
"
???}
,
 ???
...
{
???xtype:
"
textfield
"
,
???name:
"
times
"
,
???fieldLabel:
"
登錄次數
"
???}
??],
 ??buttons:[
...
{text:
"
加載表單數據
"
,
????handler:s}
]???
?}
);?
?
function
?s()
 ?
...
{
 ?f.form.load(
...
{
?????waitTitle:
"
請稍候
"
,
?????waitMsg:
"
正在加載表單數據,請稍候。。。。。。
"
,
?????url:
"
data.js
"
,
?????success:
function
(action,form)
 ?????
...
{
??????alert(
"
加載成功!
"
);
?????}
,
?????failure:
function
(action,form)
 ?????
...
{
??????alert(
"
數據加載失敗!
"
);
?????}
?????}
);?
?}
?
?}
);
?
服務器data.js中的內容為:
...
{
????success:?
true
,
 ????data:?
...
{
????????username:?
"
冷雨
"
,
????????times:?
100
????}
}
當點擊“加載表單數據”按鈕的時候,會執行f這個函數,f函數中直接調用f.form.load({})來加載表單中的數據,load方法中的參數與submit方法類似。執行上面的代碼,在從服務器端成功加載數據后,會自動把加載的數據設置到表單對應的各個字段中,然后還會執行success指定的回調函數,如圖9-23所示。 ?
圖 9-23 表單數據加載示例
二、控件的交互
一些需要從服務器加載數據的控件會自動與服務器交互,比如TreePanel下面的TreeLoader、GridPanel里面用到的Store等。這些控件其實都可以加載各種類型的數據,也就是理論上服務器可以返回任意數據給Ext客戶端,然后由Ext客戶端轉化成這些控件可以識別的數據。這些控件都提供了默認的數據解析器,能解析固定格式的數據供這些控件使用,在使用這些控件的時候,我們需要仔細看這些控件的API,看他們具體能處理什么樣格式的數據,這樣就可以在服務器端返回其默認的數據格式即可。 下面,我們來看TreePanel,這是Ext中用來顯示樹結構的控件,該控件可以通過一個url來加載樹的節點信息,并支持異步樹節點加載方式。看下面使用TreePanel的代碼:
var
?root
=
new
?Ext.tree.AsyncTreeNode(
...
{
??id:
"
root
"
,
??text:
"
樹的根
"
}
);
 ?
var
?tree
=
new
?Ext.tree.TreePanel(
...
{
??renderTo:
"
hello
"
,
??root:root,
 ??loader:?
new
?Ext.tree.TreeLoader(
...
{url:
"
treedata.js
"
}
),
??width:
100
?}
);
在代碼中,treedate.js表示服務器的程序,Ext在渲染這棵樹,需要加載樹節點的時候會向服務器發起一個請求,通過這個請求的返回結果來加載樹的節點信息。默認情況下Ext要求服務器端返回的是一個包含樹節點信息的JSON數組,格式如下: [{節點對象1},{節點對象2}] 比如treedata.js中可以包含下面的數據:
[
...
{
????????id:?
1
,
????????text:?
'
子節點1
'
,
????????leaf:?
true
????}
,
...
{
????????id:?
2
,
????????text:?
'
兒子節點2
'
,
 ????????children:?[
...
{
????????????id:?
3
,
????????????text:?
'
孫子節點
'
,
????????????leaf:?
true
????????}
]
???}
]
下面是樹的顯示結果: ?
再比如GridPanel,用于顯示表格數據,GridPanel控件使用Store來存放表格中的數據,而Ext中的Store通過DataReader來解析數據,不同的DataReader可以解析不同的數據,因此在使用表格的時候,根據客戶端使用的DataReader不同,服務器端需要返回相應格式的數據。假如我們使用XmlReader,Store的定義如下: ?
var
?store
=
new
??Ext.data.Store(
...
{
??url:
"
hello.xml
"
,??
 ??reader:
new
?Ext.data.XmlReader(
...
{
???record:
"
row
"
}
,
???[
"
id
"
,
"
name
"
,
"
organization
"
,
"
homepage
"
])
??}
);?
使用該store的表格代碼如下:
Ext.onReady(
function
()
...
{?
 ?
var
?store
=
new
??Ext.data.Store(
...
{
??url:
"
hello.xml
"
,??
 ??reader:
new
?Ext.data.XmlReader(
...
{
???record:
"
row
"
}
,
???[
"
id
"
,
"
name
"
,
"
organization
"
,
"
homepage
"
])
??}
);?
 ?
var
?colM
=
new
?Ext.grid.ColumnModel([
...
{header:
"
項目名稱
"
,dataIndex:
"
name
"
,sortable:
true
}
,
 ?????
...
{header:
"
開發團隊
"
,dataIndex:
"
organization
"
,sortable:
true
}
,
 ?????
...
{header:
"
網址
"
,dataIndex:
"
homepage
"
?}
]);
 ?
var
?grid?
=
?
new
?Ext.grid.GridPanel(
...
{
??renderTo:
"
hello
"
,
??title:
"
中國Java開源產品及團隊
"
,
??height:
200
,
??width:
600
,?
??cm:colM,
??store:store,
??autoExpandColumn:
2
?}
);?
?store.load();?
?}
);
?
這里要求服務器端返回類似下面的xml數據:
<?
xml?version="1.0"?encoding="UTF-8"
?>
<
dataset
>
?
<
row
>
??
<
id
>
1
</
id
>
??
<
name
>
EasyJWeb
</
name
>
??
<
organization
>
EasyJF
</
organization
>
??
<
homepage
>
www.easyjf.com
</
homepage
>
?
</
row
>
?
<
row
>
??
<
id
>
2
</
id
>
??
<
name
>
jfox
</
name
>
??
<
organization
>
huihoo
</
organization
>
??
<
homepage
>
www.huihoo.org
</
homepage
>
?
</
row
>
?
<
row
>
??
<
id
>
3
</
id
>
??
<
name
>
jdon
</
name
>
??
<
organization
>
jdon
</
organization
>
??
<
homepage
>
www.jdon.com
</
homepage
>
?
</
row
>
?
<
row
>
??
<
id
>
4
</
id
>
??
<
name
>
springside
</
name
>
??
<
organization
>
springside
</
organization
>
??
<
homepage
>
www.springside.org.cn
</
homepage
>
?
</
row
>
</
dataset
>
三、?Ext.Ajax.request方法
其實,不管是FormPanel的處理,還是控件的交互,他們在訪問服務器端的時候,90%都是通過使用Ext.Ajax.request方法來進行的,該方法可以用來向服務器端發送一個http請求,并可以在回調函數中處理返回的結果。往遠程服務器發送一個HTTP請求,發送Ajax調用的時候該方法的簽名如下: Ext.Ajax.rquest( [Object options] ) : Number
服務器的響應是異步的,因此需要在回調函數中處理服務器端返回的數據。回調函數可以定義在request方法調用的參數options中。另外,在request方法中可以定義Ajax請求的一些其它屬性。參數options是一個對象,該對象包含了Ajax請求所需的各種參數及回調處理參數等。options中可以包含的各個屬性及含義如下所示: url?String?指定要請求的服務器端url,默認值為Ajax對象中配置的URL參數值。 params?Object/String/Function?指定要傳遞的參數,可以是一個包含參數名稱及值的對象,也可以是name=xx&birthday=1978-1-1類似的url編碼字符串,或者是一個能返回上述兩種內容的函數。 method?String?指定發送Ajax請求使用的method,可以是GET或POST方式。默認情況下,如果請求中沒有傳遞任何參數則使用GET,否則使用POST。 callback?Function?指定Ajax請求的回調函數,該函數不管是調用成功或失敗,都會執行。傳遞給回調函數的參數有三個,第一個options表示執行request方法時的參數,第二個success表示請求是否成功,第三個參數response表示用來執行Ajax請求的XMLHttpRequest 對象。關于XMLHttpRequest可以通過http://www.w3.org/TR/XMLHttpRequest/查詢詳細的信息。 success?Function?指定當Ajax請求執行成功后執行的回調函數,傳遞給回調函數兩個參數,第一個參數response表示執行Ajax請求的XMLHttpRequet對象,第二個參數表示執行request方法時的options對象。 failure?Function?指定當請求出現錯誤時執行的回調函數,傳遞給回調函數兩個參數,第一個參數response表示執行Ajax請求的XMLHttpRequet對象,第二個參數表示執行request方法時的options對象。 scope?Object?指定回調函數的作用域,默認為瀏覽器window。 form?Object/String?指定要提交的表單id或表單數據對象。 isUpload?Boolean?指定要提交的表單是否是文件上傳表單,默認情況下會自動檢查。 headers?Object?指定請求的Header信息。 xmlData?Object?指定用于發送給服務器的xml文檔,如果指定了該屬性則其它地方設置的參數將無效。 jsonData?Object/String?指定需要發送給服務器端的JSON數據。如果指定了該屬性則其它的地方設置的要發送的參數值將無效。 disableCaching?Boolean?是否禁止cache。
比如,下面是一個向服務器foo.ejf這個應用程序發起一個Ajax請求的應用示例程序:
function
?successFn(response,options)
...
{
alert(
'
請求成功了
'
);
}
function
?failureFn(response,options)
...
{
alert(
'
請求失敗了
'
);
}
Ext.Ajax.request(
...
{
???url:?
'
foo.ejf
'
,
???success:?successFn,
???failure:?failureFn,??
 ???params:?
...
{?foo:?
'
bar
'
?}
}
);

這里的回調函數返回中返回的參數是一個XHR(即XmlHttpRequest)對象,我們可以通過該對象的responseText或responseXML等屬性來得到從服務器端返回的數據信息。在Ajax應用中,我們經常會讓服務器端返回JSON數據,由于JSON數據是字符串,因此在程序中需要先把他解析成javascript對象才可以使用,把JSON數據解析成javascript對象可以直接使用Ext.decode方法。 假如服務器返回的是下面的JSON數據對象: { ??????? username: "冷雨", ??????? times: 1 } ?則回調函數中應用這樣來使用該對象:
function
?successFn(response,options)
...
{
var
?obj
=
?Ext.decode(response.responseText)?;
alert(obj.username);
}
??? Ext.Ajax.request是Ext與服務器端交互的核心,因此需要在應用中靈活使用。在下一篇文章中,我會對Ext應用中的服務器程序作介紹。本文的文字、代碼及圖片等均來源于《ExtJS實用開發指南》,版權歸原作者所有,該指南當前在北京、深圳、成都、重慶、沈陽、杭州、上海等城市均已經可以直接到服務點購買,具體聯系方式:http://www.vifir.com/stations.html。)。
Feedback
# re: Ext服務器交互技術詳解(一) 回復 更多評論
2008-04-22 10:00 by
頂~~~ 就需要這樣的資料
|