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不應該只包含業務邏輯,同時應該使用大量的展現邏輯,針對不同用戶、不同來源、不同瀏覽器展現最優體驗。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM