自己寫一個 Handlebar helper

LuLu
6 min readApr 7, 2023

--

在使用 Handlebars 的時候,我發現 Helper 功能非常方便,可以讓我直接在模板中撰寫原本需要 JavaScript 去實作的邏輯。然而,我也發現一些基本但經常使用的功能卻沒有現成的 Helper 提供,例如比較 a 和 b 是否相等的 Helper,因此我決定自己動手寫一個。

(以下內文為自己的學習理解,可能會有錯誤部分,請看的人加減看就好)

實作

開始寫一個自己的handlebars-helper

可以使用 Handlebars.registerHelper() 來註冊一個新的helper

Handlebars.registerHelper('isSame', function(inputA, inputB, options) {
// 偵測 A 跟 B 是否相同
// 相同的話回傳{{else}} 上面的內容
// 不同的話回傳 {{else}} 下面的內容
})

“isSame” 是我們自定義的名稱,inputA 跟 inputB 是我們設定屬性,之後用來比對。options 是一個handlebars 幫我們設定的物件,這之後在講。

這就是一個 if / else 判斷式。

開始寫判斷

Handlebars.registerHelper('isSame', function(inputA, inputB, options) {
// 偵測 A 跟 B 是否相同
if (inputA === inputB){
} else {
}
})

這樣就寫好了,偵測出來是true 就回傳 {{else}}上面的內容,false 就回傳下面內容

Options

options 是 handlebars 的一個屬性物件,可以用來做很多功能,options 物件內有幾個東西可以讓我們拿來使用:

options.fn(this) : 當Helper Function的值為 true 時顯示當前內容

options.inverse(this) : 當Helper Function的值為 false 時顯替代內容,在Helper Block中使用就會顯示 {{else}} 後的內容

options.hash : 獲得輸入時為 key-value pairs 的參數

options.data : 用來在不同helper層次傳遞跟紀錄資訊,當在一個 helper 中嵌套另一個 helper 時,使用 **options.data**可以將資訊從外層傳遞到內層,也可以在內層中將資訊儲存起來以便外層存取。

依照目前的需求我只需要使用 options.fn 跟 options.inverse 就可以了

Handlebars.registerHelper('isSame', function(inputA, inputB, options) {
// 偵測 A 跟 B 是否相同
if (inputA === inputB){
return options.fn(this)
} else {
return options.inverse(this)
}
})

寫好後有兩種方式可以啟用這個Helper

方法一

直接 require 來讓這檔案跑一次,handlebars.registerHelper 就會登記這個 helper 讓你來使用

// app.js
require('./helper.js')

方法二

也可以不使用 handlebars.registerHelper 的方式,而是直接把 helper 寫成正常 function 在包裝在一個 helpers 物件內,最後在把這物件裝到 handlebars 的 helper function 裡面

// helper.js
const myHelper = {
isSame : function(inputA, inputB, options) {
// 偵測 A 跟 B 是否相同
if (inputA === inputB){
return options.fn(this)
} else {
return options.inverse(this)
}
}
}
// app.js
const myHelper = require('./helper')
app.engine('handlebars', handlebars({
defaultLayout: 'main',
helpers: myHelper
}))

在 handlebars 裡面使用

最後在需要使用的handlebars檔案中使用就可以了,

// index.handlebars
<p>name 1 is : {{name}}</p>
<p>name 2 is : {{name2}}</p>
<p>name 3 is : {{name3}}</p>
{{#isSame name name2}}
name 1 and name 2 is same
{{else}}
name 1 and name 2 not same
{{/isSame}}
<br>-------<br>{{#isSame name2 name3}}
name 2 and name 3 is same
{{else}}
name 2 and name 3 not same
{{/isSame}}

在瀏覽器內顯示 HTML

name 1 is : Wick
name 2 is : John
name 3 is : John
name 1 and name 2 not same
-------
name 2 and name 3 is same

這樣一個簡單的 isSame helper 就做好了,可以用來比對是否相同非常方便~

補充:# Block Helper

{{ #myHelper }} 跟 {{ myHelper }} 的差別是有使用“#” 是一個block helper, 例如剛剛做的 isSame 就是一個 block helper.

Normal Helper {{ helper }} : 會接受一些輸入,最後回傳一個 string 出來

toUpperCase: function (string) {
return string.toUpperCase()
}
{{toUpperCase name1}}

Block Helper {{ #helper }} … {{/helper}} : 會接受開頭到結尾一整塊的內容當成輸入最後回傳一個string 出來,在 block 裡面可以做 判斷式,迴圈,跟一些更複雜的處理。

--

--