1. 程式人生 > >freemarker實現通用布局的模板拆分與復用

freemarker實現通用布局的模板拆分與復用

表達 代碼 user layout size 復制代碼 translate 4.3 允許

原文:http://www.hawu.me/coding/733

一、基礎頁面布局

假設我們項目頁面的通用布局如下圖所示:

技術分享圖片

實現這樣的布局的基本html代碼如下:

XHTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <html> <head> </head> <body> <div style="width: 700px; text-align:center; font-size:30px;"> <div style="">header</div>
<div style="width:30%; height:300px; float:left; "> sidebar</div> <div style="width:70%; height:300px; float:left; "> main content</div> <div style="">fotter</div> </div> </body> </html>

這樣看起來很簡潔是吧,但實際上一個頁面的代碼是很淩亂的。如果我們每個前端頁面都是基於這個布局,只是main content的內容有所不同。那麽從模板的可復用角度來考慮,我們就應該header、siderbar、fotter作為單獨的模板剝離出來。然後在渲染main content頁面時候加載這些通用的模板。

二、freemarker基礎語法

2.1 插值 ${…}

freemarker會將花括號內表達式的計算結果替換到這個花括號的位置${…}。比如

1 2 <b>hello, ${user.name}</b> 5 + 2 = ${5+2}

那麽這個模板在freemarker處理後會輸出(假定user.name=”funway”)

1 2 <b>hello, funway</b> 5 + 2 = 7

2.2 <#…>與<@…>

<#…>表示freemarker內建的指令,比如<#macro>、<#if>、<#list>、<#assign>。

<@…>表示用戶自定義的指令,自定義指令要先用<#macro>宏來定義。(參見2.4)

2.3 <#include>與<#import>

include指令表示在當前位置插入其他文件的內容。比如<#include “/copyright.html”>

import指令表示將一個文件作為一個命名空間引入到當前文件。標準寫法是<#import “filePath” as nameSpace>。就像java的命名空間一樣,防止兩個文件中相同的變量名或者自定義指令名沖突。然後就可以在當前模板中使用${nameSpace.variable}和<@nameSpace.command>來調用該命名空間的變量與指令了。

include引入文件的內容(包括其中自定義的變量與指令),但import只會引入變量與指令,不會把html寫入。

2.4 <#macro>

參考官方文檔

macro宏用來定義自定義指令。基本語法是

技術分享圖片

name 表示自定義的指令名

param 可選,表示指令參數

nested 可選,表示嵌套內容

return 可選,表示到這就結束了,後面代碼不執行了

2.4.1 簡單的macro

1 2 3 4 5 6 7 <#-- 用macro定義一個sayHello指令 --> <#macro sayHello> <b>hello, world</b> </#macro> <#-- 調用上面定義的sayHello指令 --> <@sayHello/>

上面這段模板輸出的html文本如下:

1 <b>hello, world</b>

2.4.2 帶參數的macro

1 2 3 4 5 6 7 <#-- 用macro定義一個帶參的sayHelloTo指令 --> <#macro sayHelloTo person> hello, <b>${person}</b> </#macro> <#-- 調用上面定義的帶參sayHelloTo指令 --> <@sayHelloTo person="funway"/>

這個模板的輸出結果如下:

1 hello, <b>funway</b>

2.4.3 嵌套內容

1 2 3 4 5 6 7 8 9 10 11 12 13 <#macro sayHello> hello, world. <br/> <#-- 在這裏嵌入指令調用時候要嵌套的內容 --> <#nested> <br/> form: funway </#macro> <@sayHello> <#-- 這裏寫上需要嵌套的內容 --> this is nested content. </@sayHello>

這段模板的輸出如下:

1 2 3 4 5 hello, world. <br/> this is nested content. <br/> form: funway

三、布局模板拆分

使用freemarker的macro、import、include指令,我們可以將布局模板拆分為如下幾個文件

技術分享圖片

defaultLayout.ftl XHTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <#macro layout> <html> <head> </head> <body> <div style="width: 700px; text-align:center; font-size:30px;"> <#include "header.ftl"> <#include "sidebar.ftl"> <#-- 在這裏嵌入main content --> <#nested> <#include "footer.ftl"> </div> </body> </html> </#macro>

header.ftl XHTML
1 <div style="">header</div>

sidebar.ftl XHTML
1 2 3 <div style="width:30%; height:300px; float:left; "> sidebar </div>

footer.ftl XHTML
1 <div style="">fotter</div>

那麽在任何一個使用該布局的頁面,我們只要寫如下的代碼,修改要嵌入到layout中的main content就好了。

page.ftl XHTML
1 2 3 4 5 6 7 8 9 10 11 <#-- 引入布局指令的命名空間 --> <#import "../layout/defaultLayout.ftl" as defaultLayout> <#-- 調用布局指令 --> <@defaultLayout.layout> <#-- 將下面這個main content嵌入到layout指令的nested塊中 --> <div style="width:70%; height:300px; float:left; "> main content</div> </@defaultLayout.layout>

而且如果要更換布局,比如修改header,也不用每個頁面都去改一遍了。這就實現了模板的可復用。

四、題外話,關於freemarker的一些小細節

4.1 判斷變量是否存在或者為null

freemarker不允許在模板中調用一個不存在或者為null的變量,否則會直接出錯退出。所以在輸出一個變量之前盡量先判斷該變量是否存在:

技術分享圖片

freemarker實現通用布局的模板拆分與復用