在上一篇筆記中我們了解到要如何利用模板引擎配合express呈現出我們想要的頁面,雖然已經大概了解到handlebars的用途,但對於有多實用應該還沒有特別的感覺!這篇文章將要介紹如何將變數傳給view樣板使用,以及handlebars的小幫手:helpers!你可以在這邊取得起始的檔案跟著操作一遍!
在views內使用變數
實作時我們經常需要在樣板中呈現變數,比方說當使用者John登入時你會希望頁面上顯示的是
“Hi I’m John"而非一成不變的"Hi I’m Danny",在handlebars中這類的使用非常的簡單方便!
你會需要經過以下兩步驟
- 在對應的endpoint中宣告變數,並將變數傳入view樣板
- 在樣板中套用變數
我知道這聽起來很莫名其妙,實際操作一遍就很清楚了,我們就用剛剛提過的例子做示範。
因為目前我們只有一個endpoint,於是我們就在那宣告我們的變數,並告訴view樣版我們要使用的變數
app.js
app.get('/', (req, res) => {
const user_name = 'John' //加入這行
res.render('index', { name: user_name }) //修改這個部分
})
注意到我們修改的部分,我們除了宣告變數外,另外還告訴index這個樣板,在樣板中看到name這個變數時要帶入user_name的值,也就是John。
當然,若是變數與你在樣板中用的名稱一樣,你也可以採用ES6的shorthand
res.render(‘index’, { user_name })
這樣樣板中看到user_name也會自動帶入John。
了解這樣的邏輯後,之後就要進行第二步驟,也就是在樣板中套入變數。
views/index.handlebars
<h1>hi I'm {{name}}</h1>
利用兩個大括號便可在樣板中使用變數,非常方便吧!
運行程式後,去localhost:3000確認一下結果,你應該會看到這樣的畫面。

認識helpers
helpers是handlebars內一個重要的概念,它讓我們可以在樣板中進行一些基本的邏輯判斷。
舉個例子來說,今天如果使用者是登入的狀態,那頁面上就要出現登出按鈕,反之要出現登入按鈕;抑或是我打算一次在頁面上印出數筆資料,這些要求都可以藉由helpers輕易達成。
以下我將介紹我最常用的幾種內建helpers(built-in helper)
完整的說明文件你可以在這裡觀看,但我必須說,我認為官方說明文件寫得稍微有些艱澀。
each
each是handlebars內的迭代器(iterator),可以方便我們在樣板中印出多筆資料。
我們先在app.js的endpoint中建立兩個陣列,方便我說明它的用途。
app.js
app.get('/', (req, res) => {
const user_name = 'John'
const users = [{ name: 'Danny', id: 1 }, { name: 'Smith', id: 2 }, { name: 'Sara', id: 3 }]
const users2 = ['Wang', 'Cheng', 'Ting']
res.render('index', { name: user_name, users, users2 }) // 注意在這邊我使用了ES6的縮寫法
})
接著一樣到樣板中使用我們的變數,只是這次我們要配合each helper使用
views/index.handlebars
<h1>hi I'm {{name}}</h1>
<ul>
{{#each users2}}
<li>{{this}}</li>
{{/each}}
</ul>
<ul>
{{#each users}}
<li>{{this.name}}</li>
{{/each}}
</ul>
要理解以上的程式碼,首先你要知道以上的結構是在handlebars中使用helper的方式,基本的架構都是相同的,會以#起頭,/結尾,中間則是你想要呈現的HTML結構。
{{#helper名稱 要套用helper的變數}}
中間的HTML結構
{{/helper名稱}}
而each helper的作用便是迭代你套入的變數,在這個範例中是兩個不同的陣列。
我們先看一下第一個helper block內發生了什麼事情。
首先我們迭代users2這個陣列,其中包含了三個人名,也就是總共會增加三個li清單圖示
其中this表示當前跑到的陣列元素,這樣應該就可以了解等等的輸出結果了!
接著我們看一下第二個 helper block ,概念基本上相同,只是這次陣列內的元素改為物件形式,所以需要透過類似物件資料的存取方式去印出使用者名稱。
完成以上兩個步驟後,再次運行程式並去本地端確認 你應該會看到這樣的畫面。

這樣就完成each的基本使用了! each在handlebars中是個經常使用的東西,未來當你從資料庫抓資料要呈現時都會用到each~!是個很實用的小幫手!
if/unless
if/unless是基本上完全相同的概念,只是使用時機正巧相反! 這邊就一同做說明,以下我會以if為例子說明。這兩個helper讓我們可以在樣板中做簡單的邏輯判斷,像是我們一開始舉的例子,若使用者是登入狀態,就要顯示出登出按鈕,反之亦然。這類的邏輯判斷在網頁建構時很常出現,我們看一下如何使用吧~!
首先我們回到app.js 在剛剛建立的陣列中加一項屬性,方便我做說明。
app.js
app.get('/', (req, res) => {
const user_name = 'John'
const users = [{ name: 'Danny', id: 1, isLogin: true }, { name: 'Smith', id: 2, isLogin: true }, { name: 'Sara', id: 3, isLogin: false }]
const users2 = ['Wang', 'Cheng', 'Ting']
res.render('index', { name: user_name, users, users2 })
})
接著到index.handlebars中使用if helper,這邊我想要做出的效果是:若使用者為登入狀態,名字右邊出現綠色的online字樣,反之則出現紅色的offline字樣。
views/index.handlebars
<h1>hi I'm {{name}}</h1>
<ul>
{{#each users2}}
<li>{{this}}</li>
{{/each}}
</ul>
<ul>
{{#each users}}
<li>{{this.name}}
{{#if this.isLogin}}
<span style="color: green">online</span>
{{else}}
<span style="color: red">offline</span>
{{/if}}
</li>
{{/each}}
</ul>
我們先看一下輸出的結果,很好 跟我們預期的一模一樣!

if helper的使用方式也相當單純,當變數的值為true便印出夾在中間的HTML結構,也可以像一般的條件式中加入else block,就像上方的範例一樣。特別要注意的是,if helper只能做單一值的判斷,而不能做運算式的判斷。以下的情況皆會報錯
{{#if 2>0}}
<h1>heloo~</h1>
{{/if}}
{{#if users.length ===3 }}
<h1>heloo~</h1>
{{/if}}
if helper使用的時機非常的廣泛,登入/登出的按鈕切換、使用者狀態變更等都會使用到這樣的功能,雖然方便但缺點也很明顯:無法做複雜的條件判斷,這時候你會需要客製化的helper幫忙,這個會在下篇文章說明!
結語
這篇文章中我們介紹了如何把變數傳到view樣板中使用,並且介紹了handlebars中兩個常用的built-in helper以及它們的基本應用,下篇文章我們會探討如何自訂helper來讓我們的開發更加順暢!