Node.js初學筆記9 進一步了解express-handlebars:變數使用與認識helper

一篇筆記中我們了解到要如何利用模板引擎配合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來讓我們的開發更加順暢!

發表留言