首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

精通 Grails 用 Groovy 服务器页面(GSP)改变视图(3)

精通 Grails 用 Groovy 服务器页面(GSP)改变视图(3)

高级自定义标记更复杂的标记中可以处理属性和标记体。例如,现在的版权标记还需要许多复制/粘贴工作才能满足需求。我想像下面这样将当前的行为放在真正可重用的标记内:        <g:copyright startYear="2002">FakeCo Inc.</g:copyright>。        清单 11 显示了代码:
清单 11.处理属性和标记体的 Grails 标记
1
2
3
4
5
6
7
8
9
10
11
12
class DateTagLib {
  def thisYear = {
    out << Calendar.getInstance().get(Calendar.YEAR)
  }

  def copyright = { attrs, body ->
    out << "<div id='copyright'>"
    out << "&copy; ${attrs['startYear']} - ${thisYear()}, ${body()}"
    out << " All Rights Reserved."
    out << "</div>"
  }
}




请注意:attrs 是标记属性的        HashMap。在这里用它提取 startYear 属性。我将以闭包形式调用 thisYear 标记(这与我用大括号时从 GSP 页面所做的闭包调用相同)。类似地,body 也以闭包的形式传递给标记,所以调用它的方式与调用其他标记的方式相同。这样确保了我的自定义标记可以按照任意深度嵌套到 GSP 中。
您可能注意到,自定义 TagLibs 使用与标准 Grails TagLibs 相同的名称空间 g:。如果需要将自己的 TagLibs 放在自定义名称空间内,请向 DateTagLib.groovy 中添加 static namespace = 'trip'。在 GSP 内,TagLib 现在应该是        <trip:copyright startYear="2002">FakeCo Inc.</trip:copyright>。
片断模板自定义标记是重用简短代码的好方法,从而避免成为只能复制/粘贴的 scriptlet。但是对于更大块的 GSP 标记来说,可以使用片断模板
片断模板在 Grails 文档中的官方称谓是模板。惟一的问题是模板 这个词用得太多了,在 Grails 中有许多不同的意义。下一节就会看到,将安装改变搭建视图的默认模板。对这些模板的修改也包括本节要讨论的片断模板。为了减少混淆,我从 Rails 社区借用了一个术语,将要表达的内容称为片断模板,或者就称为片断
片断模板是一大块能够在多个 Web 页面之间共享的 GSP 代码。例如,假设我要在所有页面底部使用一个标准的页脚。为了实现这一目的,我要创建一个名为 _footer.gsp 的代码片断。前面的下划线是对框架的提示(对开发人员也是个明显的提示),告诉框架这不是个完整的格式良好的 GSP。如果我在 grails-app/views/trip 目录中创建这个文件,那么只有 Trip 视图才会看到它。我要将它保存在 grails-app/views 目录内,这样就能供所有页面全局共享。清单 12 显示了全局共享页脚的片断模板:
清单 12. Grails 片断模板
1
2
3
4
5
6
7
<div id="footer">
  <copyright startYear='2002'>FakeCo, Inc.</g:copyright>

  <div id="powered-by">
    <img src="${createLinkTo(dir:'images', file:'grails-powered.jpg')}" />
  </div>
</div>




可以看到,片断模板支持用 HTML/GSP 语法进行表达。对比之下,自定义 TagLib 是用 Groovy 编写的。简要来说,TagLibs 一般情况下用来封闭小行为更合适,而片断模板更适于重用布局元素。
为了让这个示例能正常工作,还需要将 “Powered by        Grails” 按钮下载到 grails-app/web-app/images 目录(请参阅 )。在下载页面上会看到其他许多附属内容,从高分辨率的 logo 到 16x16 大小的 favicons(浏览网站时在浏览器地址栏前显示的图标)。
清单 13 显示了如何在 list.gsp 页面底部包含新建的页脚:
清单 13.呈现片断模板
1
2
3
4
<html><body>
...
<render template="/footer" />
</body></html>




请注意,在呈现模板时,要去掉下划线。如果在 trip 目录下保存 _footer.gsp,那么前面的斜杠也要省略。可以这样认为:grails-app/views 目录是视图层次结构的根。
自定义默认搭建有了一些良好的、可测试的、可重用的组件之后,可以将它们做为默认搭建的一部分。这部分内容是在将 def scaffold = Foo 放入控制器之后动态生成的。默认搭建也是输入 grails generate-views Trip 或 grails generate-all Trip 时生成 GSP 的来源。
要定制默认搭建,请输入 grails install-templates。这样会在项目中加入新的 grails-app/src/templates 目录。应该看到三个目录,名为 artifacts、scaffolding 和 war。
artifacts 目录容纳各种 Groovy 类的模板:        Controller、DomainClass、 TagLib,等等。例如,如果想让所有控制器都扩展一个抽象父类,那么可以在这里进行修改。全部新控制器都将基于修改过的模板代码(有些人会加入 def scaffold = @artifact.name@,这样动态搭建就会成为所有控制器的默认行为)。
war 目录包含所有 Java EE 开发人员都熟悉的 web.xml 文件。如果需要添加自己的参数、过滤器或 servlet,请在这里进行操作(JSF 爱好者们:注意到了吗?)在输入 grails war 时,这里的 web.xml 文件就会被包含到生成的 WAR 内。
scaffolding 目录包含动态生成的视图的原始内容。请打开 list.gsp 并将        <render template="/footer"/> 添加到文件底部。因为这些模板是所有视图共享的,所以一定要使用全局片断模板。
调整了列表视图之后,现在需要验证修改是否生效。对默认模板的修改是少数需要重新启动服务器的操作之一。Grails 重新启动之后,请用浏览器访问        http://localhost:9090/trip-planner/airline/list。如果正在使用 AirlineController 的默认搭建,那么在页面底部就应该出现新的页脚。
返回列表