Velocity模板开发常见问题分享

在twitter上看到 @Fenng 提到“国内分享velocity的不多”,忽然想起自己在支付宝用velocity开发了两年,和服务端开发同学也常为这个模板层的归属问题纠结不休。这也是我在淘宝上买这件velocity主题T恤的原因,上次去红京鱼吃饭,工友们对它表示了很大的兴趣^_^

直入话题,把自己这两年的velocity开发经验的精华部分分享出来吧,相信足以应对前端模板开发的日常工作。这里我准备了一个VM版的,有运行环境的同学可以放上去跑起来看看。

问:遇到vm模板开发的问题一般怎么解决?

首先官方手册PDF还是要收藏一份,英文的看不了,就去google上搜份中文手册看。手册上没有提及的只有去google.com(google.cn基本搜不到)上搜索了,用上一些英文关键字一般可以找到,实在找不到只有问周围的专业人士了。

问:如何通过URL传递整型变量到VM里?

这个问题是我在做项目的时候遇到的一个实际问题,传一个参数进来,然后运算下。当时在国外一篇很老的归档帖子中看到了解决方案。set一个新整型,然后调用它的parseInt方法把string转成int,再进行计算,代码如下:
#set($n = $!request.getParameter('n'))
#set($intNum = 0)
#set($m = $intNum.parseInt($n) + 1)

 

问:#parse和$tile.setTemplate()(或$control.setTemplate())区别是啥?

  • #parse是先插入后解析,$tile是先解析后插入。
  • #parse和被#parse的页面变量相互共享,$tile变量需要传入。
  • #parse是代码块无须controller,$tile是通用组件需要controller。
  • #parse需要配置系统的默认path,推荐能用#parse就不要用$tile

问:VM模板里能取到哪些业务的值?

VM是模板解析层,一般可以通过$request取到很多业务数据。比如从当前request对象中取cookie:

#foreach($cookie in $request.getCookies())
$cookie.name : $cookie.value
#end

 

问:${catge}、$!catge、$catge这些写法有啥区别?

这三种写法语义上是等价的。${catge}比$catge的好处是,可以用{}符号隔开变量和其他文字。$catge和$!catge区别在于当页面中不存在$catge时,$!catge将会不会再页面中显示。

问:VM里的循环、取对象什么的咋搞?

循环啥的,学会怎么用#foreach语句就好了,想知道更多去Google下velocity的参考文档。循环能做的事情很多,比如上面的遍历出request里的cookie。

这里举个绑定一系列元素的JS表单校验的例子:

"attach3": {
desc: "附件3",
depends : true,
required: true
},
"attach4": {
desc: "附件4",
depends : true,
required: true
},
"attach5": {
desc: "附件5",
depends : true,
required: true
},

 

千万别copy大段相通的VM代码,用这句:

#foreach ( $count in [3..5] )
"attach${count}": {
desc: "附件${count}",
depends : true,
required: true
},
#end

 

如果attch5是最后一个绑定元素呢?那最后一个逗号“,”就不要打出来,这里就引申出一个问题:怎样判断是否为循环的最后一次?

这里要用到一个叫$velocityCount的变量,任何循环语句中都默认有这么一个标识当前循环次数的变量,而数组的长度都可以通过size()方法获取到。

源码:

#set($array = [3,4,5])
#foreach ( $count in $array )
"attach${count}": {

desc: "附件${count}",
depends : true,
required: true
}#if($velocityCount !=$array.size()),
#end
#end

 

问:听说VM里有宏定义,这个啥东东?

宏定义#macro就是把一些操作封装成类似function的方式来统一处理同类问题,具体你自己去google吧。有兴趣的话建议搜索系统当中叫macros-default.vm(或macros.vm)的文件,一般的宏定义都会写在这个文件里。
需要说明的是,宏定义一般是放在某car的根目录上,在页面上也可以直接定义。宏定义修改之后需要deploy当前系统,否则方法会被缓存,看不到改动后的效果。

问:VM里怎样生成随机数

VM强大之处其实在于它的工具类,例如一般的VM都默认有$stringUtil这个字符串比较的类。
有时我们需要给URL后加个随机数清清缓存。在webx系统你可以用$randomUtils.nextDouble(),在sofa MVC试试$math.getRandom(),如果不起作用,检查下是否配置了相应的工具类。

问:如何通过VM来获取当前页面URL?

貌似前面已经提到VM可以随意调用$request对象里的方法,获取到需要的值。

//webx下获取当前页:
$rundata.getRequest().getServerName()$rundata.getRequest().getServletPath()
//sofa MVC下获取当前页:
#set($pageAbsUrl = "$!request.getServerName()"+"$!request.getContextPath()"+"$!request.getServletPath()")
//获取引用页:
$rundata.getRequest().getHeader("referer")

 

问:VM该前端开发来做还是服务端开发来做?有啥意义?

@catge认为服务端提供数据、接口,前端进行VM、CSS、JS开发。因为VM是DOM结构层,样式和脚本都要基于结构开发。
比如有一个需求是为某些浏览器的用户增加一个全站的XBOX弹窗,提醒用户升级到股沟浏览器。你有两种选择方案,一种是用JS判断UA信息为该浏览器,然后将已经生成好的XBOX的DOM弹出来。第二种方案是在VM里取request里的http头信息里的UA信息,判断符合条件则生成这段DOM。
咋一看,这两种方法差不多,而且通过VM来实现更复杂,因为VM里取浏览器类型和版本号十分困难,$stringUtil折腾来折腾去都没有JS来得快。
但是如果需求方说的浏览器是指IE6.0以下版本的浏览器呢?为了几千个用户给几亿用户的前端代码里加上这段JS判断?那只能说你很2。
@catge认为VM层的模板优化至关重要,VM不应该只包含业务逻辑,同时应该使用大量的展现逻辑,针对不同用户、不同来源、不同浏览器展现最优体验。

 

posted @ 2010-06-30 15:25  猫哥_kaiye  阅读(5189)  评论(0编辑  收藏  举报