iT邦幫忙

2021 iThome 鐵人賽

DAY 13
1
Modern Web

ZK 30天速成系列 第 13

資料驅動的元件

資料驅動繪製 (Model-driven Rendering)

英雄列表範例已經初步展示過 Listbox 的用法,你應該可以觀察到它的架構也可分成 MVC三個角色,Listbox 會根據你所指定的資料物件來繪製子元件 Listitem,當你呼叫 ListModel的 method 來變更資料量的時候(如 add(), remove(), clearAll()),ListModel 內部會通知 Listbox 並更新畫面。

靜態與動態產生的差別

ZK 支援直接在 zul 中定義元件與子元件,這是「靜態產生」元件,例如:

<listbox id="box">
		<listhead sizable="true">
			<listheader label="name" sort="auto" />
			<listheader label="gender" sort="auto" />
		</listhead>
		<listitem>
			<listcell label="Mary" />
			<listcell label="FEMALE" />
		</listitem>
		<listitem>
			<listcell label="John" />
			<listcell label="MALE" />
		</listitem>
		<listitem>
			<listcell label="Jane" />
			<listcell label="FEMALE" />
		</listitem>
		<listitem>
			<listcell label="Henry" />
			<listcell label="MALE" />
		</listitem>
</listbox>

而「動態產生」元件就是要創造一個 ListModelList 給元件,雖然兩種方法產生的元件功能相同,不過內部運作稍有不同。主要的差別在於:「狀態儲存的位置不同:資料驅動繪製的元件,狀態儲存與控制都在資料模型 (ListModel),而靜態產生的狀態是存在元件中」

以 Listbox 為例,資料驅動繪製的狀況下,要取得被選擇的項目是要從 ListModelList 中取得:

model.getSelection(); //回傳資料物件如 Hero

Listbox.getSelectedItem() 回傳的是被選擇的 Listitem,而不是資料。

用 Java 選擇項目也一樣:

model.addToSelection(hero); //傳入資料物件而不是 Listitem

如果要啟用多選模式,也是呼叫 ListModelList.setMultiple(true) 而不是元件上 Listbox.setMultiple()

String[] names = {"Mary", "John", "Jane", "Henry"};
ListModelList model = new ListModelList(names);
model.setMultiple(true);

在 ZK 的元件中,許多元件都支援這樣的特性,不過他們可以支援的 model 類別不同。

支援 ListModel

  • Chosenbox
  • Combobox
  • Grid
  • Listbox
  • Searchbox
  • Selectbox
  • Tabbox

支援 TreeModel

  • Tree
  • Organigram

繪製器

先前英雄列表範例中提到用 <template> 定義繪製的範本,但如果你要在執行期根據各種情況來繪製時怎麼辦呢?對應 <template>的 Java 作法就是實作繪製器介面,不同的元件需要實作不同的介面,如 Listbox 需要實作 ListitemRenderer,範例如下:

public class MyRenderer implements ListitemRenderer{
		public void render(Listitem listitem, Object data, int index) {
				Listcell cell =new Listcell();
				listitem.appendChild(cell);
				if (datainstanceof String[]){
					cell.appendChild(new Label(((String[])data)[0].toString()));
				}elseif (datainstanceof String){
					cell.appendChild(new Label(data.toString()));
				}else {
					cell.appendChild(new Label("UNKNOW:"+data.toString()));
				}
		}
}

實作完成後,可透過 透過 Listbox.setItemRenderer(String) 來指派,或是

<listbox itemRender="quickstart.MyRenderer"/>

上一篇
使用者輸入驗證
下一篇
Shadow Element:控制 UI 元件的元件
系列文
ZK 30天速成30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言