簡單擴(kuò)展讓beetl html標(biāo)簽支持父子嵌套

字號:


    默認(rèn)情況下,beetl的html標(biāo)簽并不支持父子嵌套,就像類似jsp標(biāo)簽?zāi)菢樱笜?biāo)簽需要知道子標(biāo)簽的信息,子標(biāo)簽也需要知道父標(biāo)簽信息。但是beetl只需要簡單擴(kuò)展,就能完成嵌套標(biāo)簽支持。
    首先看一個(gè)最終的使用效果,實(shí)現(xiàn)倆個(gè)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,這個(gè)類是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類,這個(gè)類其實(shí)就是一個(gè)樹形結(jié)構(gòu),記錄了parent的context,記錄了當(dāng)前tag信息,以及記錄了子tag的context,這樣,每個(gè)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);
    }
    如上代碼所示,但渲染某個(gè)htmltag前(調(diào)用super.render()前),可以從request里獲取nestcontext,如果沒有,生成一個(gè)新的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),需要知道有多少個(gè)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 是一個(gè)注冊方法,獲取當(dāng)前context.可以自行開發(fā)一個(gè)