Ext2.0的選擇需要冒很大的風險,确實Ext在界面上能夠有很大的提升,但是用戶端機器的性能和網絡方面的制約,再加上Ext本身沒有很好的實作工具支援。從編碼角度來說,可能需要花費更多的時間,這相對于直接的Web開發。如果項目中缺少美工,又對通路性能或并發量不是特别的要求的Web開發,可以考慮使用,譬如說安全裝置的控制界面。當然項目組成員必須忍受大量javascript編碼。
一般來說,Ext使用如下:
Ext 作為前台,Spring-Hibernate-Stucts作為整體的控制層,json-lib作為兩者的互動。
當然背景是什麼無所謂了,主要就是json字元串的拼湊
流程稍微記錄了一下,後面有些不想寫了,是以邏輯有些混亂。
1. Json-Lib
導入依賴庫
commons-beanutils.jar
commons-collections-3.1.jar
commons-lang-2.1.jar
commons-logging.jar
ezmorph-1.0.4.jar
json-lib-2.2-jdk15.jar
測試Bean類

public class TestBean ...{
String date1 = "111";
int date2 = 10;
public String getDate1() ...{
return date1;
}
public void setDate1(String date1) ...{
this.date1 = date1;
public int getDate2() ...{
return date2;
public void setDate2(int date2) ...{
this.date2 = date2;
測試代碼
JSONObject jsonBean = JSONObject.fromObject(new TestBean());
System.out.println(jsonBean);
List list = new ArrayList();
list.add(new TestBean());
JSONArray jsonList = JSONArray.fromObject(list);
System.out.println(jsonList);
輸出:
{"date1":"111","date2":10}
[{"date1":"111","date2":10},{"date1":"111","date2":10}]
正式使用再做一下字元串處理
2. Ext使用
将整個Ext2.0的目錄導入到MyEclipse中去
Docs可以全部删去,example 也可删去部分
隻保留examples根目錄下的内容
在examples\examples.js中的開頭修改成
Ext.BLANK_IMAGE_URL = 'ext-2.0/resources/images/default/s.gif';
将指向Ext網站的s.gif檔案指向本地
添加 ext-fix.js 修正radio等Form控件從json資料擷取資訊時,工作不正常的問題

Ext.form.BasicForm.prototype.setValues = function(values)...{
if(values instanceof Array)...{
for(var i = 0, len = values.length; i < len; i++)...{
var v = values[i];
var f = this.findField(v.id);
if(f)...{
if ( f.getEl().dom.type == 'radio' ) ...{
var group = this.el.dom.elements[f.getName()];
for (var i=0; i < group.length; i++ ) ...{
if(group[i].__ext_field) ...{
group[i].__ext_field.setValue(group[i].value == v);
if(this.trackResetOnLoad)...{
group[i].__ext_field.originalValue = group[i].__ext_field.getValue();
else
...{
f.setValue(v.value);
f.originalValue = f.getValue();
}else...{
var field, id;
for(id in values)...{
if(typeof values[id] != 'function' && (field = this.findField(id)))...{
if( field.getEl().dom.type == 'radio' ) ...{
var group = this.el.dom.elements[field.getName()];
group[i].__ext_field.setValue(group[i].value == values[id]);
field.setValue(values[id]);
field.originalValue = field.getValue();
return this;

Ext.form.Radio.prototype.onRender = function(ct, position) ...{
Ext.form.Radio.superclass.onRender.call(this, ct, position);
this.el.dom.__ext_field = this;

Ext.form.Radio.prototype.setValue = function(v) ...{
if(v === true || v === 'true' || v == '1' || v === false || v === 'false' || v == '0') ...{
// Select all radios of this group
var radios = this.el.up('form').select('input[type=radio]');
// Uncheck all other values
for(var i = 0; i < radios.elements.length; i++) ...{
if(radios.elements[i].__ext_field && radios.elements[i].__ext_field != this && radios.elements[i].name == this.el.dom.name)
radios.elements[i].__ext_field.checked = false;
// DOM checked is set by the browser
radios.elements[i].__ext_field.fireEvent("check", this, this.checked);
this.checked = (v === true || v === 'true' || v == '1');
if(this.el && this.el.dom) ...{
this.el.dom.checked = this.checked;
this.fireEvent("check", this, this.checked);
在使用Ext項目中将所有的檔案的編碼調到UTF-8,這包括js檔案和頁面檔案。因為Ext核心使用UTF-8編碼,在表單送出和Grid時表現得比較明顯。
使用Ext時,在頁面檔案的<head></head>中加入下面内容
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Forms</title>
<link rel="stylesheet" type="text/css" href="ext-2.0/resources/css/ext-all.css"/>
<!-- GC -->
<!-- LIBS -->
<script type="text/javascript" src="ext-2.0/adapter/ext/ext-base.js"></script>
<!-- ENDLIBS -->
<script type="text/javascript" src="ext-2.0/ext-all.js"></script>
<script type="text/javascript" src="ext-2.0/build/locale/ext-lang-zh_CN.js"></script>
<script type="text/javascript" src="ext-2.0/ext-fix.js"></script>
<!-- Common Styles for the examples -->
<link rel="stylesheet" type="text/css" href="ext-2.0/examples/examples.css"/>
<script type="text/javascript" src="ext-2.0/examples/examples.js"></script>
這一部分可以制作頁面模闆
每個獨立的頁面 再加入自己獨特的js邏輯,以dynamic.js為例
<script type="text/javascript" src="dynamic.js"></script>
如果頁面需要div的話,就加入即可。
3. Form
表單制作包括送出和資料内容的填充
制作Ext Form表單, 可以使用Ext form builder來簡化一些操作。
Ext Form Builder同樣使用Ext開發
首先添加一個Form Panel
然後将所需要的Form控件拖到Form Panel上即可
選擇Show/Edit JSON就可以看到生成表單所需要的javascript語句
1) 表單送出
制作上面的這個表單
兩個Edit,一個Combo和一個Radio,代碼中有些布局資訊也可以使用Form Builder來制作,但是Form Builder不支援%的布局方式,可以手工改寫生成界面的json來達到效果。
表單送出時,使用各個控件name值作為請求參數
這裡的控件都有些布局資訊,可以忽略
l Edit控件

columnWidth : .5,
layout : 'form',
border : false,
items : [...{
xtype : 'textfield',
fieldLabel : '姓名',
name : 'name',
anchor : '90%'
}]
如果需要填寫預設值的話,加入value參數即可
送出時也是使用最新的value值來送出的
l Radio控件

columnWidth : .25,
style : 'margin-top:5px',
xtype : 'radio',
fieldLabel : '性别',
boxLabel : '男',
name : 'sex',
checked : true,
inputValue : 'M',
anchor : '95%'

}, ...{
labelWidth : 0,
labelSeparator : '',
hideLabels : true,
fieldLabel : '',
boxLabel : '女',
inputValue : 'F',
Radio使用inputValue來作為送出值,接收時也使用這個值
l Combo控件
Combo控件擷取資訊的Json字元串格式

...{totalProperty:100,root:[...{retrunValue:1, displayText:'中文1'},...{retrunValue:2, displayText:'中文2'},...{retrunValue:3, displayText:'中文3'},...{retrunValue:4, displayText:'中文4'},...{retrunValue:5, displayText:'中文5'},...{retrunValue:6, displayText:'中文6'}]}
這裡使用combo.jsp來傳回這些資訊
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
response.setCharacterEncoding("UTF-8");
String json = "{totalProperty:100,root:[";
json += "{retrunValue:1, displayText:'中文1'},"
+"{retrunValue:2, displayText:'中文2'},"
+"{retrunValue:3, displayText:'中文3'},"
+"{retrunValue:4, displayText:'中文4'},"
+"{retrunValue:5, displayText:'中文5'},"
+"{retrunValue:6, displayText:'中文6'}]}";
response.getWriter().write(json);
%>
擷取的資料源

var ds = new Ext.data.Store(...{
proxy: new Ext.data.HttpProxy(...{url:'combo.jsp'}),
reader: new Ext.data.JsonReader(...{
totalProperty: 'totalProperty',
root: 'root'
}, [
...{name: 'retrunValue', type: 'int'},
...{name: 'displayText'}
])
});
'totalProperty' json中記錄的總數量
'root' json中資料開頭的标示
'retrunValue' 和'displayText' 為資料對象的字段名稱, 其中'retrunValue'為int類型
從combo.jsp中擷取json資料将組裝成定義資料源類型
Combo使用這個資料源

xtype:'combo',
store: ds,
valueField :"retrunValue",
displayField: "displayText",
mode: 'local',
forceSelection: true,
blankText:'請選擇學曆',
emptyText:'選擇學曆',
hiddenName:'education',
editable: false,
triggerAction: 'all',
allowBlank:false,
fieldLabel: '學曆',
name: 'education',
anchor:'90%'
Combo的值為"retrunValue",顯示使用"displayText"
當然最後不要忘記将ds進行load
l 儲存按鈕将表單資訊進行送出

buttons : [ ...{
text : '儲存',
handler : function() ...{
if (simpleForm.form.isValid()) ...{
this.disabled = true;
simpleForm.form.doAction('submit', ...{
url : 'test.jsp',
method : 'post',
params : '',
success : function(form, action) ...{
Ext.Msg.alert('成功', action.result.data);
this.disabled = false;
//document.location.href = 'hello.html';
},
failure : function() ...{
Ext.Msg.alert('失敗', '抱歉');
儲存按鈕将表單資訊送出給test.jsp,我們将所有的請求參數列印出來,并傳回結果資訊
request.setCharacterEncoding("UTF-8");

try...{
String name;
java.util.Enumeration pNames=request.getParameterNames();
while(pNames.hasMoreElements())...{
name=(String)pNames.nextElement();
System.out.println(name+"="+request.getParameter(name));

}catch(Exception e)...{
System.out.print(e.toString());
out.print("{success:true, data:age=567}");
列印處來的例子
age=dfgg
name=ddfgdfg
sex=M
education=3
傳回參數也必須是json字元串,success表示操作成功,或失敗
action.result.data會取=後的值
2) 表單接收資訊
隻需要傳回和表單相符的JSON字元串
{success:true,data:{"name":'你好',"age":'131',education:3,sex:'F'}}
formget.jsp檔案内容
out.print("{success:true,data:{"name":'你好',"age":'131',education:3,sex:'F'}}");
取消按鈕從formget.jsp中擷取這個字元串資訊,來填充表單
buttons : [
...

text : '取消',
simpleForm.form.load( ...{
url : 'formget.jsp',
method : 'get',
params : ''
當然也可以在開始時,就調用來導入資料
4. Grid
Grid所需要的json字元串
{totalProperty:100,root:[{id:1,name:'二月DD1',descn:'descn1'},{id:2,name:'二月DD2',descn:'descn2'},{id:3,name:'二月DD3',descn:'descn3'},{id:4,name:'二月DD4',descn:'descn4'},{id:5,name:'二月DD5',descn:'descn5'},{id:6,name:'二月DD6',descn:'descn6'},{id:7,name:'二月DD7',descn:'descn7'},{id:8,name:'二月DD8',descn:'descn8'},{id:9,name:'二月DD9',descn:'descn9'},{id:10,name:'二月DD10',descn:'descn10'}]}
Grid.jsp 根據起始值和限制數量決定傳回json字元串
//response.setCharacterEncoding("UTF-8");
String start = request.getParameter("start");
String limit = request.getParameter("limit");

try ...{
int index = Integer.parseInt(start);
int pageSize = Integer.parseInt(limit);
//String json = "{totalProperty:100,root:[";
for (int i = index; i < pageSize + index; i++) ...{
json += "{id:" + i + ",name:'二月DD" + i + "',descn:'descn" + i + "'}";
if (i != pageSize + index - 1) ...{
json += ",";
json += "]}";
//out.print(json);

} catch(Exception ex) ...{
擷取資料時,如此通路grid.jsp檔案
grid.jsp?start=1&limit=10
Grid使用
Grid中字段定制
var cm = new Ext.grid.ColumnModel([

...{header:'描述',dataIndex:'id'},

...{header:'姓名',width:100, sortable:true,dataIndex:'name'},

...{header:'描述',dataIndex:'descn'}
]);
Header 顯示名稱
dataIndex 從ds查找字段
width 字段寬度
sortable 是否允許排序
Grid中使用資料源的定義,從grid.jsp中擷取資料

proxy: new Ext.data.HttpProxy(...{url:'grid.jsp'}),
...{name: 'id'},
...{name: 'name'},
...{name: 'descn'}
定義GridPanel建立Grid

var grid = new Ext.grid.GridPanel(...{
el: 'grid',
width:600,
ds: ds,
cm: cm,
bbar: new Ext.PagingToolbar(...{
pageSize: 10,
displayInfo: true,
displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
emptyMsg: "你好"
})
grid.render();
el為grid.html中id為grid的div塊
ds 資料源
cm grid顯示列定義
bbar bottom toolbal下面的工具欄
這裡使用分頁控件
最後ds導入時候,使用參數進行過濾
ds.load({params:{start:0,limit:10}});
擴充一下,将上面的Form放入到grid中來
在Grid上添加一個工具欄,通過單擊工具欄中Add Something按鈕,彈出上面的Form資訊
修改如下:

tbar:[...{
text:'Add Something',
tooltip:'Add a new row',
iconCls:'add',
handler : onItemClick
}, '-', ...{
text:'Options',
tooltip:'Blah blah blah blaht',
iconCls:'option'
},'-',...{
text:'Remove Something',
tooltip:'Remove the selected item',
iconCls:'remove'
}],
在GridPanel添加在Grid上的Toolbar,Toolbar上添加三個按鈕,并為Add Something添加單擊事件onItemClick。
單擊事件
var win;

function onItemClick(item) ...{
//alert(item.text);
if (!win) ...{
var simpleForm = new Ext.FormPanel( ...{
el : 'hello-tabs',
labelAlign : 'left',
title : '你好',
buttonAlign : 'right',
bodyStyle : 'padding:5px',
width : 600,
frame : true,
labelWidth : 80,
xtype : "textfield",
fieldLabel : "Text",
name : "textvalue"
layout : 'column',
labelSeparator : ':',
items : [ ...{
fieldLabel : '年齡',
name : 'age',
xtype : 'combo',
store : ds,
valueField : "retrunValue",
displayField : "displayText",
mode : 'local',
forceSelection : true,
blankText : '請選擇學曆',
emptyText : '選擇學曆',
hiddenName : 'education',
editable : false,
triggerAction : 'all',
allowBlank : false,
fieldLabel : '學曆',
name : 'education',
]
win = new Ext.Window( ...{
el : 'hello-win',
layout : 'fit',
width : 500,
height : 300,
closeAction : 'hide',
plain : true,
items :
simpleForm,
ds.load();
win.show(this);
唯一需要注意的是儲存和取消按鈕需要加入Ext.Window做控制,并且要注意FormPanel和Ext.Windows所要渲染的div塊,并且這些塊必須在grid.html中進行定義
<div id="hello-win" class="x-hidden">
<div class="x-window-header">Hello Dialog</div>
<div id="hello-tabs">
<!-- Auto create tab 1 -->
<div class="x-tab" title="Hello World 1">
<p>Hello...</p>
</div>
<!-- Auto create tab 2 -->
<div class="x-tab" title="Hello World 2">
<p>... World!</p>
5. Tree
直接使用Ext例子
Tree所需要的json字元串
[{id:300,text:'01',cls:'task-folder',children:[{id:'2',text:'01-01',leaf:true, cls:'task'},{id:'3',text:'01-02',children:[{id:'4',text:'01-02-01',leaf:true},{id:'5',text:'01-02-02',leaf:true}]},{id:'6',text:'01-03',leaf:true}]},{id:'7',text:'02',leaf:true}]
text"-->顯示的文本
"id"-->id值 ,單擊事件時可以使用
"leaf"-->Boolean值,如果"葉子"是真的話,則不能包含子節點Children nodes
"cls"-->選用的樣式,通常在這裡標明圖示
"href"-->指定的url,還有一個"hrefTarget"的屬性
children -〉表示子節點資訊
在Record.css中自定了兩個定義的css,task和task-folder
.task .x-tree-node-icon {
background-image:url(icons/cog.png) ;
.task-folder .x-tree-node-icon{
background-image:url(icons/folder_go.png) !important;
Json字元串中就使用了這個值
Tree使用如下,相對比較簡單
var Tree = Ext.tree;

var tree = new Tree.TreePanel(...{
el:'tree-div',
autoScroll:true,
animate:true,
enableDD:true,
containerScroll: true,
loader: new Tree.TreeLoader(...{
dataUrl:'record.jsp'
// set the root node

var root = new Tree.AsyncTreeNode(...{
text: 'Ext JS',
draggable:false,
id:'source'
tree.setRootNode(root);
// render the tree
tree.render();
root.expand();
6. Layout
左邊為樹型控件,右邊為TabPanel,顯示的頁面
當左邊樹型控件被點選後,右邊的所有的Tab進行變化,通路與樹型清單id相對應的頁面内容
l 布局使用
布局一般使用Viewport
var viewport = new Ext.Viewport({
隻要注意region和el即可
region:'north',
el:'north-div',
el和contentEl的差別
el是第一層div, contentEl一般指向更内部的div
l Tab使用
普通的Tab通路未有無法顯示js的問題
{
title: 'Ajax Tab 1',
autoLoad:{url:'grid.html',scripts:true}
是以就使用了Ext論壇中提供的一個Iframe的擴充 Ext.ux.ManagedIFrame
使用時将miframe.js檔案導入即可

var tabs2 = new Ext.TabPanel( ...{
// renderTo: document.body,
region : 'center',
el : 'center-center', // 大的
//contentEl : 'center-center', // 小的
activeTab : 0,
height : 250,
defaults : ...{
autoScroll : true
items : [
xtype : "panel",
title : "Personal Assistant",
body : new Ext.ux.ManagedIFrame( ...{
autoCreate : ...{
id:'person', // 設定通路的名稱
src : 'dynamic.html',
frameBorder : 0,
cls : 'x-panel-body',
width : '100%',
height : '100%'
title : "Personal",
id:'person2', // 設定通路的名稱
src : 'grid.html',
l 樹型控件
要給樹型控件添加單擊事件

tree.on('click', function(node) ...{
// do something
alert(node.id + ' was activated.');
Ext.get('person').dom.src = 'grid.html?selectedid='+node.id;
單擊後,通過查找ManagedIFrame形成的Tab頁的id,并且将其屬性src改變來達到Tab頁内容改變的效果
參考:
Ext2_0 form使用執行個體 - 天曉得的專欄 - CSDNBlog
Ext 2_0布局執行個體
[2_0][SOLVED] Best practices for getting - saving form data - Ext JS Forums
[EXT Develop Log]--comboBoxradioFix it! - kkbear - JavaEye技術網站
ext學習-tree元件-線上閱讀-新書城
對《Ext2_0 form使用執行個體》的一點補充 - 天曉得的專欄 - CSDNBlog
用Ext 2_0 combobox 做的省份和城市關聯選擇框 - 天曉得的專欄 - CSDNBlog
關于ext和struts的互動 - Allen_CD_China - JavaEye技術網站
從Java 類産生json(json-lib) - windfree - BlogJava
學習EXT第XX天
流氓臨遠, 沒人性洋芋's ext tutorial
And Others, I can't remember