說明:只是說明一些需要注意的東西,更多的學習參考Tapestry官方文檔
1、For
source:是對應的java類里的List 對象或者是個數(shù)組 需要抽象 或者提供set get方法
value:是循環(huán)這個source對象代表當前的一個 ,需要在page文件中設置問一個屬性,可以不在對應的java類里有這個屬性
index:是循環(huán)的索引值 同value一樣 在page文件中設置一個屬性即可 <property name="index"/>
在循環(huán)的時候 會自動為vlaue和index賦當前的值
2、Foreach 和For一樣使用
3、Hidden組件 總是多余S的處理
<input jwcid="@Hidden" type="hidden" value="ognl:blahblah" encode="false"/>
4、 Insert 組件
e.g.
<input type="text" jwcid="name@Insert" value="ognl:user.name"/>
頁面表現(xiàn)時,將會到頁面類中尋找getUser().getName()方法獲取初值并輸出
相當于在頁面上顯示數(shù)據(jù).
5、 TextField 組件
e.g.
<input type="text" jwcid="username@TextField" value="ognl:username"/>
頁面表現(xiàn)時,將會到頁面類中尋找getUsername()方法獲取初值
*如果是修改信息頁面,通常初始值要在頁面表現(xiàn)之前由setUsername()手動設置從數(shù)據(jù)庫中讀取出來的值
表單提交時,通過setUsername()寫入新值(即用戶輸入值),在類中通過getUsername()獲取新值
相當于在修改個人信息時,首先讀出用戶名賦予文本框(用戶名)初值,用戶修改時填入新值,后臺獲取之
*Hidden屬性區(qū)分是普通文本輸入框(默認false)和密碼輸入框(hidden="ognl:true")
readonly屬性設置只讀 readonly="true"為只讀(后臺可讀取)
*disabled屬性設置是否可寫 diabled="true"為不可寫(后臺也不可讀取)
6、 TextArea 組件
e.g.
<textarea jwcid="content@TextArea" value="ognl:content" cols="40" rows="10"></textarea>
頁面表現(xiàn)時,將會到頁面類中尋找getContent()方法獲取初值
工作原理同TextField
7、 RadioGroup/Radio 組件
e.g.
<span jwcid="headImage@RadioGroup" selected="ognl:headImage">
<input jwcid="@Radio" type="radio" value="1"/>頭像1
<input jwcid="@Radio" type="radio" value="2"/>頭像2
<input jwcid="@Radio" type="radio" value="3"/>頭像3
<input jwcid="@Radio" type="radio" value="4"/>頭像4
<input jwcid="@Radio" type="radio" value="5"/>頭像5
<input jwcid="@Radio" type="radio" value="6"/>頭像6
</span>
RadioGroup為每一個Radio提供一個唯一的ID。RadioGroup跟蹤當前被選中的屬性值,并且只有一個Radio能夠被選中.
頁面提交時,RadioGroup組件就利用OGNL表達式向headImage字段寫入被選中的Radio組件的value參數(shù)值.
頁面表現(xiàn)時(修改頁面),將會到頁面類中尋找getHeadImage()方法獲取初值,然后尋找@Radio組件中與其相同的組件并勾選上.
8、 PropertySelection 組件
使用PropertySelection組件必須要構(gòu)造一個類來實現(xiàn)IPropertySelectionModel接口,并且重寫該接口的5個方法.
public int getOptionCount() //提供下拉菜單的長度
public Object getOption(int index) //提供select標簽的option
public String getLabel(int index) //提供select標簽的Label值,也就是下拉菜單顯示的內(nèi)容
public String getValue(int index) //提供select標簽的value值
public Object translateValue(String value) //selected后的返回值,value值未必就是我們需要的返回值,可以在這個方法里面對返回的value做對應的轉(zhuǎn)換或修改.
e.g.1. 性別下拉框
<select jwcid="gender@ProPertySelection" name="genderSelect" value="ognl:gender" model="supportedGender">
<option selected>先生</option>
<option>女士</option>
</select>
代碼
GenderSelectionModel.java
public class GenderSelectionModel implements IPropertySelectionModel {
public static final String male = "先生";
public static final String female = "女士";
public static final String[] genderOptions = { male, female };
public int getOptionCount() {
return genderOptions.length;
}
public Object getOption(int index) {
return this.translateValue(genderOptions[index]);
}
public String getLabel(int index) {
return genderOptions[index].toString();
}
public String getValue(int index) {
return genderOptions[index];
}
public Object translateValue(String value) {
if (value.equals("先生")) {
return "1";
} else {
return "0";
}
}
}
代碼
ModUserInfo.java
public IPropertySelectionModel getSupportedGender() {
return new GenderSelectionModel();
}
存入數(shù)據(jù)庫中"1"代表先生,"0"代表女士,通過translateValue(String value)方法轉(zhuǎn)換
頁面表現(xiàn)時,通過model屬性給出的IPropertySelectionModel獲取下拉選項,即getSupportedGender().
然后通過getGender()方法獲取初值,比如獲取"0",則在頁面顯示時尋找value值為"0"的選項即為"女士",并選擇之作為初始選擇項.
e.g.2. 日志類型下拉框
<select jwcid="logType@PropertySelection" name="typeSelect" value="ognl:logType" model="supportedType">
<option>心情日記</option>
<option>情感天地</option>
<option>生活感觸</option>
</select>
代碼
TypeSelectionModel.java
public class TypeSelectionModel implements IPropertySelectionModel {
private List typeList = new ArrayList();
public TypeSelectionModel(List typeList) {
this.typeList = typeList;
}
public int getOptionCount() {
return typeList.size();
}
public Object getOption(int index) {
return ((LogType)typeList.get(index)).getValue();
}
public String getLabel(int index) {
return ((LogType) typeList.get(index)).getName();
}
public String getValue(int index) {
return ((LogType) typeList.get(index)).getValue();
}
public Object translateValue(String value) {
return value;
}
}
代碼
ModLog.java
public IPropertySelectionModel getSupportedType() {
TypeSelectionModel typeSelectionModel =
new TypeSelectionModel(loadType(getUser().getUserId()));
return typeSelectionModel;
}
private List loadType(int userid) {
...//從數(shù)據(jù)庫載入該用戶的日志類型列表
}
頁面表現(xiàn)時,通過model屬性給出的IPropertySelectionModel獲取下拉選項,即getSupportedType().
然后通過value屬性給出的初始值即,getLogType()方法獲取初值,比如獲取"2",則在頁面顯示時尋找value值為"2"的選項即為"生活感觸",并選擇之作為初始選擇項.
9、 Form組件
e.g.
<form jwcid="logForm@Form">
...
</form>
Form的監(jiān)聽(listener)方法可以有兩種方式:
1. 在Form組件中聲明.
<form jwcid="logForm@Form" listener="ognl:listener:onLogin">
...
</form>
2. 在submit類型組件中聲明.
<input type="submit" jwcid="onLogin@Submit" listener="listener:onLogin" value="發(fā)表"/>或者
<span jwcid="@ImageSubmit" image="..." listener="listener:onLogin"><img src="..." width="" height=""/></span>
前一種方式當Form中只要有submit就會觸發(fā)監(jiān)聽方法,后一種方式是Form中有多個submit,各自實現(xiàn)不同的監(jiān)聽方法.
G) Foreach 組件
e.g.
<span jwcid="@Foreach" source="ognl:logList" value="ognl:item">
循環(huán)組件,遍歷source參數(shù),在表現(xiàn)其內(nèi)容前更新value參數(shù),將Foreach組件所包含的內(nèi)容重復表現(xiàn),其中可以通過value參數(shù)獲取所需顯示內(nèi)容.
本例中,頁面表現(xiàn)時通過getLogList()方法獲取日志列表,循環(huán)取出其中數(shù)據(jù)更新item(日志對象)并予以顯示.其中item需要在頁面規(guī)范(.page)文件中聲明:
<property name="item"/>
*class參數(shù)用來尋找類似CSS的文件對Foreach進行修飾.
Foreach組件: class="ognl:beans.evenOdd.next"
Page文件: <bean name="evenOdd" class="org.apache.tapestry.bean.EvenOdd"/>
CSS文件: tr.odd{background-color: #ffffff;}tr.even{background-color: #eeeeee;}
10、 Conditional 組件
e.g.
<span jwcid="@Conditional" condition='ognl:item.sex.equals("1")'>先生</span>
<span jwcid="@Conditional" condition='ognl:item.sex.equals("0")'>女士</span>
conditional參數(shù)為true時運行Conditional組件中的HTML模板內(nèi)容.
在Tapestry4.0以后就不支持該組件了, 可以使用其他組件來實現(xiàn):
1. Contrib:Choose和Contrib:When
<library id="contrib" specification-path="classpath:/org/apache/tapestry/contrib/Contrib.library"/>(.application文件中引入Contrib類包)
<span jwcid="@contrib:Choose">
<span jwcid="@contrib:When" condition='ognl:user.gender.equals("1")'>先生</span>
<span jwcid="@contrib:When" condition='ognl:user.gender.equals("0")'>女士</span>
</span>
2. If組件
<span jwcid="@If" condition='ognl:item.sex.equals("1")'>先生</span>
<span jwcid="@If" condition='ognl:item.sex.equals("0")'>女士</span>
3. Else組件
<span jwcid="@Else">man</span>
【============================ts的函數(shù)執(zhí)行順序========================================】
對之前的該文章進行了一些修正,主要是針對finishLoad()方法。
我覺得對初學者會有一些幫助。
下面這幾個函數(shù)是我在使用的,它們的執(zhí)行順序依次從上到下。
1.protected void finishLoad() {} ***
2.public void pageValidate(PageEvent event) {}
3.public void activateExternalPage(Object[] parameters, IRequestCycle cycle) {}
4.public void pageBeginRender(PageEvent event) {}
// 如果有表單提交,則將form中的各字段的值賦給頁面類
5. ...... 賦值
6.public void submit() // 表單提交等用listenter:調(diào)用的方法
7.protected void prepareForRender(IRequestCycle cycle) {}
----------------------------------------------------
1.protected void finishLoad() {}
這個函數(shù)最先執(zhí)行,但是它實際上沒有什么用處(我感覺)。因為:
這個函數(shù)只在頁面池中沒有某一個頁面類、需要生成一個新的頁面對象時才調(diào)用。這里就有一個陷阱:如果你的tomcat啟動時使用了-Dorg.apache.tapestry.disable-caching=true(為了調(diào)試方便而設),那么你每次刷新頁面時,它都會執(zhí)行(因為每個request都會新生成一個頁面類對象),造成了它總是執(zhí)行的假象。在實際的部署時,會使用caching,則這個函數(shù)執(zhí)行的機會很少。所以要注意。
初始化的代碼放在4 pageBeginRender()中
2.public void pageValidate(PageEvent event) {}
如果實現(xiàn)了PageValidateListener接口,則可以在這里進行驗證,比如訪問權限等。執(zhí)行完1后,它就開始執(zhí)行。
3.public void activateExternalPage(Object[] parameters, IRequestCycle cycle) {}
如果實現(xiàn)了IExternalPage接口,則可以從這里取得由外面?zhèn)鬟^來的參數(shù)。執(zhí)行2后,執(zhí)行到這里。在這里可以把那些參數(shù)取出,賦給頁面類。
4.public void pageBeginRender(PageEvent event) {}
執(zhí)行完3后,將執(zhí)行本函數(shù)。但是這時從客戶端傳過來的參數(shù)還沒有被賦值(如果提交了表單的話)。這里可以進行一些初始化操作。
5.執(zhí)行完4后,如果有表單提交,在這里將會取出那些值,賦給對應的字段。(注意:只是將表單中有的值賦過來)
6.public void submit()
如果有表單提交的話,在這里將進行對應的操作。因為此時各字段已經(jīng)取好值了,所以可以拿來直接用。
7.protected void prepareForRender(IRequestCycle cycle) {}
最后才執(zhí)行這個方法。我們可以在其中進行為了在頁面上顯示數(shù)據(jù)而進行的操作,比如取得什么對象什么的,因為這里頁面類的屬性賦值已經(jīng)結(jié)束,可以直接拿來使用了。
注意:如果執(zhí)行了6,則還要執(zhí)行4,再執(zhí)行7。如果沒有6,4完了就直接是7。
以上是我所總結(jié)的執(zhí)行順序,不當之處請指出。
-----------------------------------------------------
最開始學tapestry的時候,覺得“怎么有這么多地方需要持久啊”。原來以前只知道pageBeginRender這個函數(shù),什么初始化操作都放在它里面。可是它是在賦值之前執(zhí)行,所以拿到的字段多都是空的,卻都以為是沒有持久化的緣故。所以在客戶端里放了一大堆的@Hidden,或者session中持久,非常麻煩,,,對tapestry也產(chǎn)生的懷疑。現(xiàn)在才知道那些需要取得客戶端傳來的參數(shù)的代碼,最好放在prepareForRender里,很多不必要的持久都可以省掉了