Grails探索之Template

                               Grails探索之Template
 
Grails开发平台在View技术方面,我最喜欢的技术除了引入了flash变量以外,就是Template技术。
Java平台在View方面最方便的重用技术就是include。虽然Tiles等功能非常强大,但由于配置的繁琐,使得它们在作为整个项目的Layout以外,几乎就没什么应用。Include虽然使用起来很方便,但是它在传值方面又有天然的弱点。
而Grails平台的Template技术,既有include的方便,没有配置的问题;又有include所欠缺的传值方面的强大。
下面我们来稍举几个例子来说明问题。
我有一个测试页面下面的一堆代码:
<input type="button" value="report3" onclick="window.location.href='<g:createLink controller="report" action="bar3" />'"></input>
                        <input type="button" value="report4" onclick="window.location.href='<g:createLink controller="report" action="bar4" />'"></input>
                        <input type="button" value="pie1" onclick="window.location.href='<g:createLink controller="report" action="pie1" />'"></input>
                        <input type="button" value="pie2" onclick="window.location.href='<g:createLink controller="report" action="pie2" />'"></input>
                        <input type="button" value="pie3" onclick="window.location.href='<g:createLink controller="report" action="pie3" />'"></input>
                        <input type="button" value="xy" onclick="window.location.href='<g:createLink controller="report" action="xy" />'"></input>
                        <input type="button" value="scatter" onclick="window.location.href='<g:createLink controller="report" action="scatter" />'"></input>
                        <input type="button" value="water" onclick="window.location.href='<g:createLink controller="report" action="water" />'"></input>
 
一共有十多行相同的button语句,虽然可以使用“拷贝”和“粘贴”的方法很快的写完这些代码,但这一行行的代码长度太长,以至于超过了显示屏的长度,使得维护起来相当的困难。
于是我想使用Template来减少代码行的长度,使得代码在视线范围内,这样便于维护。下面就是Template的制作过程:
我们常常说,Grails平台的项目使用的是契约式的编程,真的名不虚传。在Template上也使用到了契约,一般来说,以下划线开头的文件名的gsp文件都是Template。所以我把我的第一个Template命名为_test.gsp:
<input type="button" value="${value}" onclick="window.location.href='<g:createLink controller="${control}" action="${action}" />'"></input>
 
可以看到,该Template的内容是否简单,包含三个变量:value、control和action。
我们怎么来使用这个Template呢?
其实也很简单:
<g:render template="test" model="[value:'nulti',control:'report',action:'multi']"/>
 
第一是使用<g:render>标签,template为去掉下划线的Template文件名,即test,最后在model里传递Template所需要的三个参数。
真的很简单。下面再举一个例子。
我们经常需要在每一个面有的开头捕捉一些出错信息,如下所示:
<g:if test="${flash.error}">
                 <div class="errors">${flash.error}</div>
           </g:if>
 
上面的语句用来判断flash里有没有错误信息,如果有的话就打印在页面上。当然,如果我们需要将上面的语句做成Template的话,就不妨做大一些。
_message.gsp
 
           <g:if test="${flash.error}">
                 <div class="errors">${flash.error}</div>
           </g:if>
           <g:if test="${request.error}">
                 <div class="errors">${request.error}</div>
           </g:if>
           <g:if test="${flash.errors}">
                 <div class="errors">
                     <g:each in="${flash.errors}" var="error">
                     ${error}<br>
                     </g:each>
                 </div>
           </g:if>
           <g:if test="${request.errors}">
                 <div class="errors">
                     <g:each in="${request.errors}" var="error">
                     ${error}<br>
                     </g:each>
                 </div>
           </g:if>
 
在这个Template中,我们首先判断flash变量里有没有error信息,有就打印在页面上;然后再去判断request变量里有没有error信息,有的话就打印在页面上;接着去判断flash变量里有没有errors信息,有的话就一条一行的打印在页面上;最后判断request变量里有没有errors信息,有的话就一条一行的打印在页面上。
下面来看看,我们怎么使用它:
<g:render template="message"/>
 
真的太简单啦!
到了这里,你可以会问,这样的传值include也可以做到啊。不错,include是可以做到,但Template能传递对象,include呢?
_collection.gsp
 
                     <g:each in="${users}" var="user">
                     name: ${user?.name}<br>
                 </g:each>
 
是的,我传了一个名为users的List对象给了Template,然后在Template里对Users进行了遍历,打印user的名字。
下面,我们来看看如何使用该Template:
<g:render template="collection" var="users" collection="${users}" />
 
将List对象的内容放在collection变量里,然后var变量存放的是在Template里接收该List对象的变量名。
 
 

没有更多推荐了,返回首页