Ajax 支持
我们开始讨论框架对比中最有趣的地方:Asynchronous JavaScript + XML (Ajax) 的使用。
您还记得您的第一个使用 Ajax 的 Web 应用程序以及在实现时付出的艰辛吗? 没错,为了实现多浏览器的支持,所有 JavaScript 通信和数据解析代码都包含了大量技巧。客户端的实现是最麻烦的工作,与之相比,Servlet 工作更加轻松。
然而,现在随着诸如 Tapestry 和 Wicket 这类框架的使用,在一个应用程序中增加一个 Ajax 操作只需要几行代码和几分钟的时间。这种操作非常简单。以下的示例描述了一种简单的场景:单击 to-dos 列表中的某一项将使用相应的数据更新(以 Ajax 模式)预览面板。
Tapestry 将链接的 async 参数设置为 true,并且,如果必要的话,定义链接应该更新的组件的列表,如清单 37、38 和 39 所示:
清单 37. Tapestry 页面说明片段
<component id="previewReceivedItem" type="DirectLink">
<binding name="listener" value="listener:onPreviewItem"/>
<binding name="parameters" value="ognl:currentItem.itemId"/>
<binding name="async" value="true"/>
<binding name="updateComponents" value="ognl:{'preview'}"/>
</component>
<component id="preview" type="Any"/>
<component id="previewSubject" type="Insert">
<binding name="value" value="ognl:previewSubject"/>
<binding name="renderTag" value="true"/>
</component>
<component id="previewState" type="Insert">
<binding name="value" value="ognl:previewState"/>
<binding name="renderTag" value="true"/>
</component>
<binding name="listener" value="listener:onPreviewItem"/>
<binding name="parameters" value="ognl:currentItem.itemId"/>
<binding name="async" value="true"/>
<binding name="updateComponents" value="ognl:{'preview'}"/>
</component>
<component id="preview" type="Any"/>
<component id="previewSubject" type="Insert">
<binding name="value" value="ognl:previewSubject"/>
<binding name="renderTag" value="true"/>
</component>
<component id="previewState" type="Insert">
<binding name="value" value="ognl:previewState"/>
<binding name="renderTag" value="true"/>
</component>
清单 38. Tapestry 页面说明片段 Java 类
public abstract class ListPreviewActionItems extends BasePage {
public abstract String getPreviewSubject();
public abstract void setPreviewSubject(String previewSubject);
public abstract String getPreviewState();
public abstract void setPreviewState(String PreviewState);
public void onPreviewItem(Integer itemId) {
if (itemId != null) {
ActionItem pitem = getActionItemManager().getActionItemByItemId(itemId);
setPreviewSubject(pitem.getSubject());
setPreviewState(pitem.getCurrentState());
}
}
}
public abstract String getPreviewSubject();
public abstract void setPreviewSubject(String previewSubject);
public abstract String getPreviewState();
public abstract void setPreviewState(String PreviewState);
public void onPreviewItem(Integer itemId) {
if (itemId != null) {
ActionItem pitem = getActionItemManager().getActionItemByItemId(itemId);
setPreviewSubject(pitem.getSubject());
setPreviewState(pitem.getCurrentState());
}
}
}
清单 39. Tapestry 页面说明片段 HTML 标记
<h3>Preview Action Item</h3>
<div jwcid="preview">
Subject: <span id="previewSubject" jwcid="previewSubject">subject</span><br/>
State: <span id="previewState" jwcid="previewState">current state</span>
</div>
<div jwcid="preview">
Subject: <span id="previewSubject" jwcid="previewSubject">subject</span><br/>
State: <span id="previewState" jwcid="previewState">current state</span>
</div>
Wicket 中只使用具有已实现的 onClick() 方法的 AjaxLink,如清单 40 和 41 所示:
清单 40. Wicket 中的 AjaxLink
public class ListPreviewActionItems extends WebPage {
public ListPreviewActionItems() {
final LoadableActionItemModel previewItem = new LoadableActionItemModel(null);
WebMarkupContainer preview = new WebMarkupContainer("preview");
preview.setOutputMarkupPlaceholderTag(true);
preview.add(new Label("previewSubject", new PropertyModel(previewItem, "subject")));
preview.add(new Label("previewState", new PropertyModel(previewItem, "currentState")));
add(preview);
AjaxLink previewReceivedItem = new AjaxLink("previewReceivedItem") {
public void onClick(AjaxRequestTarget target) {
previewItem.setItemId(currentItem.getItemId());
target.addComponent(previewContainer);
}
};
add(previewReceivedItem);
}
}
public ListPreviewActionItems() {
final LoadableActionItemModel previewItem = new LoadableActionItemModel(null);
WebMarkupContainer preview = new WebMarkupContainer("preview");
preview.setOutputMarkupPlaceholderTag(true);
preview.add(new Label("previewSubject", new PropertyModel(previewItem, "subject")));
preview.add(new Label("previewState", new PropertyModel(previewItem, "currentState")));
add(preview);
AjaxLink previewReceivedItem = new AjaxLink("previewReceivedItem") {
public void onClick(AjaxRequestTarget target) {
previewItem.setItemId(currentItem.getItemId());
target.addComponent(previewContainer);
}
};
add(previewReceivedItem);
}
}
清单 41. Wicket 的 AjaxLink HTML 标记
<h3>Preview Action Item</h3>
<div wicket:id="preview">
Subject: <span wicket:id="previewSubject">subject</span><br/>
State: <span wicket:id="previewState">current state</span>
</div>
<div wicket:id="preview">
Subject: <span wicket:id="previewSubject">subject</span><br/>
State: <span wicket:id="previewState">current state</span>
</div>
就这么简单。框架在幕后执行了通信、数据处理及所有其他棘手的工作。