默認(rèn)情況下,beetl的html標(biāo)簽并不支持父子嵌套,就像類似jsp標(biāo)簽?zāi)菢?,父?biāo)簽需要知道子標(biāo)簽的信息,子標(biāo)簽也需要知道父標(biāo)簽信息。但是beetl只需要簡單擴(kuò)展,就能完成嵌套標(biāo)簽支持。
首先看一個最終的使用效果,實(shí)現(xiàn)倆個html標(biāo)簽table.tag,tr.tag.可以在頁面上這么用:
<#table data =${userlist}>
<#tr class=3c name=name> 名稱 </#tr>
</#table>
在閱讀table.tag,tr.tag之前,先看看如何擴(kuò)展html標(biāo)簽
首先,需要擴(kuò)展 htmltagsupportwrapper,這個類是html標(biāo)簽實(shí)現(xiàn)類,我們可以擴(kuò)展此類來定制化需求,然后重新注冊覆蓋。因此實(shí)現(xiàn)類
public class htmlnesttagsupportwrapper extends htmltagsupportwrapper{
public void render(){....}
}
然后在配置文件配置tag.htmltag= bingo.util.htmlnesttagsupportwrapper 就可以生效。
htmlnesttagsupportwrapper用到了tagnestcontext類,這個類其實(shí)就是一個樹形結(jié)構(gòu),記錄了parent的context,記錄了當(dāng)前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實(shí)現(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();
//重新設(shè)置
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前(調(diào)用super.render()前),可以從request里獲取nestcontext,如果沒有,生成一個新的nestcontext。如果已經(jīng)存在。則將當(dāng)前nestcontext加入到父nestcontext。渲染完畢后,需要重置nestcontext。
最后看一下tr.tag如何實(shí)現(xiàn),tr僅僅實(shí)現(xiàn)了生成表頭
<tr class=${class}>${tagbody}</tr>
table.tag 則要麻煩點(diǎn),需要知道有多少個tr,然后輸出數(shù)據(jù),內(nèi)容如下:
<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 是一個注冊方法,獲取當(dāng)前context.可以自行開發(fā)一個
2025國考·省考課程試聽報名