模版引擎,對現在的 Web 開發極為重要,幾乎所有主流 Web 框架都會支持一種或多種模版引擎,模版引擎可以分離用戶界面和業務邏輯,工作原理主要是一種翻譯,后端對特定的標記、語法、變量等渲染后再輸送給瀏覽器,如今模版引擎已經非常強大,在相關領域可以幫助開發者節約很多時間精力,比如緩存、設計分層、插件化。不同的模版引擎千變萬化,各種語言也是層出不窮,比如 php 模版引擎中的老大哥 Smarty,Python 的 Jinja2,也是 Flask 中內置的模版引擎,如今前端也有新生模版引擎,依賴前端的性能提升,像后端一樣處理模版語言渲染數據。
Leaf 作為 Vapor 官方提供的組件之一原生集成在 Vapor 中,Leaf 模版文件以 .leaf
結尾,模版語法夾雜在 HTML 之間,我們可以直接使用而不需要引入其他外部依賴。
我們可以在路由中進行模版的渲染,同時附帶給模版傳參數,參數以 Dict 的形式放在第二個位置,然后在 .leaf
模版文件中就能拿到對應的數據。
Leaf 使用 #
作為模版語法的標記,筆者也很苦惱為啥 Vapor 的作者要用井號做語法標記,在 Github 也有人提出 #
會與 HTML/CSS
有沖突(issue #11)。
我們可以用 #()
來輸出 HTML, 這里需要注意的是這樣輸出 Leaf 會對其中的 HTML 進行轉義,舉個例子,如下代碼輸出到瀏覽器,HTML 源代碼真是內容其實是:hello
,并沒有被 A 標簽包起來。
如果想輸出原始 HTML 怎么辦呢?我們可以用 raw() {}
來輸出不會被轉移的 HTML,也就是說到瀏覽器會被解析成對應的 HTML 代碼,如下會在瀏覽器輸出:<a>hello</a>
。
需要注意的是不要讓用戶輸入內容用 #raw(){ }
進行原始輸出,比如評論,以免造成惡意代碼執行的漏洞!
下面這段代碼邏輯就是 if:elif:else
基本循環用 #loop
,第一個參數傳入數組,第二個參數寫出循環內部的實例變量名,假設我的 users
內容是 [“Objective-C”、”Swift”、”Vapor”],輸出內容在瀏覽器看起來就會是這個樣子:
Hello, Objective-C!
Hello, Swift!
Hello, Vapor!
我們構建一些多頁面 Web 程序,常常會有每個頁面或者一種頁面部分相似的內容,比如網站的頭部、腳部,頭部一般用來放導航欄,腳部放一些版權聲明、三方鏈接等等,那么在整個網站任何頁面中這兩部分的內容基本都是一致的,那么我們可以把這兩部分的內容抽出一個單獨的 .leaf
文件存放,并在需要的地方引入進來就可以了。
Leaf 提供了四個方法來引入/包含其他模版:
Import:#import("template")
Export: #export("template") { Leaf/HTML }
Extend: #extend("template")
Embed: #embed("template")
這四個標簽都不需要補全 .leaf
后綴,Leaf 會自動查找對應文件。
#import()
用來聲明一個插入點在當前模版。
#extend()
用來繼承一個模版,使用模版的內容,然后就只能用 #export()
填充之前聲明的插入點。
#embed("body")
才是用來引入一個模版的內容到當前位置。
舉個栗子
新聞熱點
疑難解答