天天看點

Tapestry 5 元件參數

Tapestry 5 元件參數     本文根據 http://tapestry.apache.org/tapestry5/tapestry-core/guide/parameters.html 翻譯整理過來,請高手指正,轉載請注明出處!     元件參數是 Tapestry 一個重要的方面。元件類執行個體的存在還不夠,它必須還要配置以達到處理正确的事情。配置依據元件參數。   一個元件可以帶有許多參數,每一個參數都有一個明确的名字、明确的 Java 類型(可以是一個簡單類型),是可選的或必須的。   參數的定義是通過在私有屬性上放置一個 Parameter annotation 。   以下列出的是一個循環元件;通過它的 start 和 end 參數(用來設定循環的邊界),元件的 body 将多次呈現( renders )。元件可以更新 value 參數(參數所在容器的屬性),它能依據 start 或 end 哪一個大來自動加減:   package org.example.app.components;

  參數名字來自屬性名(去掉首字元 "_" 和 "$" )——實際情況是比對 getter 方法 "get" 後字串。這裡的參數名字是: "start", "end" 和 "value" 。   綁定參數   上例中的元件可被其他元件或頁面的模闆( template )引用:  

  end 屬性用來綁定 Count 元件的 end 參數,這裡它被綁定到一個字元值 "3" ,它将被 Tapestry 自動強制轉換為 int 值 3 。   許多參數都可以采用這種綁定方式。   元件參數也可以通過在元件類中使用 Component annotation 來綁定。   當兩者綁定發生沖突時,用 Component annotation 綁定的參數要優先于模闆綁定的參數。   表達式綁定   前面例子模闆中的值“ 3 ”是一個表達式綁定。通過在參數值前面使用不同的字首,我們可以改變 Tapestry 如何解釋表達式的剩餘部分(冒号後面的部分):  

字首 描述
block 模闆中 block 的 id 。
component 同一模闆中另一元件的 id 。
literal 字面字元常量。
message 從分類資訊檔案( message catalog )中查找值。
prop 容器元件屬性名,用于讀寫。
translate 配置的 translator 的名字。
validate 被用來建立許多字段校驗的校驗說明。

  參數有一個預設字首,通常是 "prop:" ,未指定字首時用此字首。   屬性綁定   "prop:" 綁定字首意味着屬性綁定。   屬性綁定的表達式是一個點分隔的屬性名序列。簡單的屬性表達式就僅僅是一個屬性的名字,如: "prop:userName" 。複雜的屬性表達式可以在屬性前加上部分導航來進行讀寫,如: "prop:userData.name" 。   除了屬性名之外,我們還可以調用任意方法,方法必須是公共的、傳回一個非 void 值、抛出的異常為非檢查型的且是無參的。為區分方法名和屬性名,我們需要加上一個圓括号“ () ”。是以,先前的例可以寫成 "prop:getUserName()" 和 "prop:getUserData().getName()" 。注意當表達式最後一項是一個方法名,綁定将是隻讀的,而非可讀寫的。   這一特性對于通路标準集合類一對的屬性(沒有命名相應的屬性)來說非常有用,如 Collection.size() 或 Map.keySet() 。   一但獲值失敗,會不會因為這一表達式中存在空指針而絆倒?你可以使用 "?." 替換 "." 作為分隔符。這會增加一個空值檢測,忽略掉表達項的空值。假設 "foo?.bar?.baz" 中 foo 或 bar 為 null ,表達式将會傳回 null ,與此同時, "foo?.bar?.baz" 中如果 foo 或 bar 為 null ,則更新此表達式将轉變為一個空操作。   另外,還支援少數特殊的情況。大多數情況下,這些特殊的值可以減少你在值前面添加字首 "literal:" 。這些少數情況相當于屬性表達式:

  • "true" 和 "false" 将被轉換成布爾值。
  • "null" 将被轉換成值null。
  • "this" 将是元件自己的引用。
  • 簡單的數字值也可以被接收,這些将會被解析成Long或Double對象。比如:"prop:3.14"。
  • 被句點分隔的一個整數範圍。如:"1..10"。
  • 單引号裡的字面字元串,如:"'Hello World'"。

這些情況下,多出的空格将被忽略。對于關鍵字( "true" , "false" , "this" 和 "null" ),忽略大小寫。 這些值都是隻讀且無變化的。   驗證綁定   綁定字首 "validate:" 非常特殊,它允許一個簡短的字元串來建立和配置對象執行的表單控制元件的輸入驗證,如 TextField 和 Checkbox 。   這些字元串是一個逗号分隔的驗證類型( validator types )清單,驗證類型是對象執行驗證的簡短别名。在許多情況下,驗證是多方式可配置的:比如,一個強制最小字元長度驗證,想知道最小的字元長度是多少的,這個值被指定在一個等号( = )後面。   如: validate:required,minLength=5強制該字段域必填且最少5個字元。   TODO: More ability to escape or quote constraint values. Ability to reference methods or properties of the container to perform some of the validation. Links to proper discussion of validation, once the code and documentation is ready.   轉換綁定   綁定字首 "translate:" 也可以用在輸入驗證。它是配置項 Translator 的名字,主要負責服務端與用戶端表現資料轉換(例如,用戶端字元串與服務端數字值的轉換)。   有效的轉換( translators )清單配置在 TranslatorSource 服務中。   非正式(informal )參數   一些元件支援非正式參數,額外的參數超過了正式定義的參數。非正式參數将在元件标簽呈現時作為額外的屬性輸出。一般來說,元件與特有的 HTML 标簽有 1:1 的對應關系(比如 TextField 和 < input >支援非正式參數)。   非正式參數通常且于設定一個元素的樣式,或者指定用戶端的事件句柄(處理)。   非正式參數預設的綁定字首依賴于指定的參數綁定方式。如果參數綁定在 Java 類中的 Component annotation 裡面,這裡的預設綁定為 "prop:" ,如果參數綁定在模闆中,預設的綁定字首為 "literal:" 。這反映出用 annotation 使參數指定在 Java 類裡,很可能就是一個用來計算的值,反之,一個指定在模闆中的值将被簡單的拷貝,按照原樣輸出到 HTML (結果)流中。   參數雙向性   參數并非簡單的變量;在元件和它的容器元件(包含元件的元件)的屬性之間,每一個參數等同于一個連接配接或者說綁定,當使用字首 prop: 時,元件能将改變通過指派的方式強制到它的容器元件的屬性裡。  

  因為 Count 元件更新 value 參數( _value 屬性 ),容器元件的index屬性将被更新。在Count的body内,我們通過擴充表達式(等同于JSP中表達式語言) ${index}輸出目前index屬性的值。輸出結果大至如下:     <p> Countdown: 5 ... 4 ... 3 ... 2 ... 1 ... </p> (盡管空格完全不同) 它們的關系是元件可以讀取固定的值或者其容器元件中可變的屬性值,同樣能更改其容器元件中的屬性值。   必選參數   必選參數必須要綁定。如果一個元件有未綁定的必選參數将會發生運作時異常。   可選參數   參數不是必要的,是可選的。 我們可以設定可選參數的預設值以提供其他屬性使用。在 Count 元件中,參數 min 有預設值為 1 ,如果參數 min 綁定了一個值,則綁定的值将替代預設值。 參數的預設綁定 Parameter annotation 的 value() 屬性可以用來指定一個綁定的表達式,用以參數未綁定的情況下作為預設綁定。典型地,綁定的表達式是一個屬性的名字,這個屬性将會在運作時被計算值。 Example:

  在其他地方,我們可以在 value 上使用字首。一個普通的字首 "message:" 用以通路國際化資訊( localized message )。     計算方式的參數預設綁定   在少數情況下,我們需要用計算綁定的方式來作為參數的預設值。在此,我們要提供一個預設的無參的綁定方法,方法的傳回值用來綁定參數。傳回值可以是 Binding 執行個體或者簡單的值(比較多的使用)。   方法名以 "default" 加上首字母大寫的參數名。   使用這種方法,先前的例子可以寫成:  

: 在這個例子中,屬性表達式 "defaultMessage" 用來動态通路資訊。   以上例子可以寫得更簡潔:  

  這種形式很像使用綁定字首 "literal:" ,但是字面值是通過 defaultMessage() 方法計算出來的。   顯然,這要比簡單地指定一個預設的參數值做更多的工作。 In the few real cases where this is approach is used, the default binding method will usually deduce a proper binding, typically in terms of the component's id. For example, the TextField component will deduce a value parameter that binds to a property of its container with the same name. 這種方法在一些少量的實際情況中被采用,預設的綁定方法将通常會根據元件的 id 産生适當的綁定。比如, TextField 元件将産生 value 參數,用它容器中具有相同名字的一個屬性綁定到此 value 參數。   預設的綁定方法隻有在 Parameter annotation 未提供預設值時才被調用。   未綁定的參數   如果一個參數沒有被綁定(可選參數),那麼它的值可以在任何時候被讀寫。   更新對于未綁定的參數并沒有作用。在第一個例子中, Count 元件的 value 參數沒有綁定,這完全是可以的。   注意:更新對于這個屬性是臨時性的;當元件完成呈現時,屬性将被置為預設值。   TODO: This seems contradictory. What does it mean to update an unbound component parameter when the component is not rendering? 參數緩存   讀取一個參數值會耗費不少資源的(因為類型的強制轉換)。是以,緩存參數值是有意義的,至少當元件正在呈現自己時。極少情況下,我們可以通過設定 Parameter annotation 的 cache() 屬性為 false 來打破這種緩存機制。   參數類型的強制轉換   Tapestry 包含自動類型轉換( coecing types automatically )機制。大多情況下,它用來将字面字元串轉換成相應的值,但在許多情況下,将會發生較複雜的轉換。   參數名   預設情況, Tapestry 将去掉首字母 "$" 和 "_" 的屬性名轉換為參數名。 我們也可以使用 Parameter annotation 的 name() 屬性覆寫這種預設情況。   決定是否綁定   很少情況,我們需要根據參數是否綁定來産生不同的行為。這可以通過查詢元件資源( resources )來完成,元件資源可以通過 Inject annotation 注入到元件中:  

以上粗略舉例這種方法。因為參數類型是簡單類型 int ,我們很難區分沒有綁定和顯示地綁定 0 。   Inject annotation 将注入元件的資源( ComponentResources ),這些資源是我們寫的 Java 類與 Tapestry 底層建構我們類的類之間的橋梁。任何情況,資源一但被注入,就可以被通路。