默認情況下,Beetl的html標簽并不支持父子嵌套,就像類似jsp標簽那樣,父標簽需要知道子標簽的信息,子標簽也需要知道父標簽信息。但是beetl只需要簡單擴展,就能完成嵌套標簽支持。
首先看一個最終的使用效果,實現(xiàn)倆個html標簽table.tag,tr.tag.可以在頁面上這么用:
<#table data ="${userList}">
<#tr class="3c" name="name"> 名稱 </#tr>
</#table>
在閱讀table.tag,tr.tag之前,先看看如何擴展html標簽
首先,需要擴展 HTMLTagSupportWrapper,這個類是html標簽實現(xiàn)類,我們可以擴展此類來定制化需求,然后重新注冊覆蓋。因此實現(xiàn)類
public class HTMLNestTagSupportWrapper extends HTMLTagSupportWrapper{
public void render(){....}
}
然后在配置文件配置TAG.htmltag= bingo.util.HTMLNestTagSupportWrapper 就可以生效。
HTMLNestTagSupportWrapper用到了TagNestContext類,這個類其實就是一個樹形結構,記錄了parent的Context,記錄了當前tag信息,以及記錄了子tag的Context,這樣,每個tag都可以訪問父tag或者子tag:代碼如下
public class TagNestContext {
private Tag tag = null;
private TagNestContext parent = null;
private List<TagNestContext> children = null;
public Tag getTag() {
return tag;
}
public void setTag(Tag para) {
this.tag = para;
}
public TagNestContext getParent() {
return parent;
}
public void setParent(TagNestContext parent) {
this.parent = parent;
}
public List<TagNestContext> getChildren() {
if(children==null) children = new ArrayList<TagNestContext>();
return children;
}
public void setChildren(List<TagNestContext> children) {
this.children = children;
}
}
回頭在看看 HTMLNestTagSupportWrapper實現(xiàn)
public void render()
{
HttpServletRequest request = (HttpServletRequest)this.ctx.getGlobal("request");
TagNestContext tnc = (TagNestContext)request.getAttribute("tagContext");
if(tnc==null){
tnc = new TagNestContext();
tnc.setTag(this);
request.setAttribute("tagContext", tnc);
super.render();
request.removeAttribute("tagContext");
}else{
TagNestContext child = new TagNestContext();
child.setParent(tnc);
child.setTag(this);
tnc.getChildren().add(child);
request.setAttribute("tagContext", child);
super.render();
//重新設置
request.setAttribute("tagContext", child.getParent());
}
}
public String getTagName(){
return (String)this.args[0];
}
public Object get(String attr){
Map map = (Map)this.args[1];
return map.get(attr);
}
如上代碼所示,但渲染某個htmltag前(調用super.render()前),可以從request里獲取NestContext,如果沒有,生成一個新的NestContext。如果已經(jīng)存在。則將當前NestContext加入到父NestContext。渲染完畢后,需要重置NestContext。
最后看一下tr.tag如何實現(xiàn),tr僅僅實現(xiàn)了生成表頭
<tr class="${class}">${tagBody}</tr>
table.tag 則要麻煩點,需要知道有多少個tr,然后輸出數(shù)據(jù),內容如下:
<table>
${tagBody}
<% for(var item in data){%>
<tr>
<%
var tag = getTagContext();
var children = tag.children;
for(var tdTagCtx in children){
print("<td>");
var tdTag = tdTagCtx.tag;
var name = tdTag.tagName;
var value = item[name];
print(value);
println("</td>");
}
%>
</tr>
<%} %>
</table>
etTagContext 是一個注冊方法,獲取當前context.可以自行開發(fā)一個
更多信息請查看IT技術專欄