標籤:des style http io os 使用 ar java for
http://fraserxu.me/posts/Using-Handlebarsjs-with-Expressjs/
在Express項目中使用Handlebars模板引擎
31 Aug 2014
最近在用Expressjs做一個項目,前後端都用它來完成。自己之前有用過Express一段時間,但是大部分都是用它來編寫Restful的API,而沒有真正用它所提供的前端頁面渲染功能。
所以嚴格意義來講這是第一次完整的項目。開始做之後就遇到了一些需要做出決定的地方。眾所周知,Express的預設範本引擎是Jade.我在之前學習Express的時候,因為它是預設的引擎,所以有接觸和使用過一段時間,感覺也還行。Jade在編寫頁面時所提供的嵌套功能比較實用,可以節省很大的代碼量。
Jade is a high performance template engine heavily influenced by Haml and implemented with JavaScript for node. For discussion join the Google Group.
上面是Jade Github所在頁面的描述。可以得知它是一個注重效能,受Hamle影響,並特別針對Nodejs而編寫的前端模板引擎。
我們先來看一下Jade官方頁面所給的例子:
doctype 5html(lang="en") head title= pageTitle script(type=‘text/javascript‘). if (foo) { bar(1 + 5) } body h1 Jade - node template engine #container.col if youAreUsingJade p You are amazing else p Get on it! p. Jade is a terse and simple templating language with a strong focus on performance and powerful features.
我們可以看到,對比原生的HTML, Jade明顯的一個優勢就是標籤數量上的減少。很多地方只要按照約定的縮排規則編寫,完全可以避免使用原生HTML時標籤忘記閉合的問題。同時Jade還提供了一些用於渲染判斷的條件,可以根據資料來決定顯示的內容等功能。
另外Jade的遍曆資料產生頁面功能,配合使用Json資料時特別好用,可以很大程度上減少代碼量。
而另外一個原因,也是覺大多數人使用Jade的原因,可能都跟我一樣,因為是Express架構內建的模板引擎,而它的作者也是鼎鼎有名的TJ.
看了標題也許會奇怪,既然Jade出自大神之手,而且簡單易用,我為什麼還要去選擇Handlebarsjs呢?
同樣我們看下官方描述:
Handlebars provides the power necessary to let you build semantic templates effectively with no frustration.
Mustache templates are compatible with Handlebars, so you can take a Mustache template, import it into Handlebars, and start taking advantage of the extra Handlebars features.
作為一個模板引擎,它繼承於著名的Mustache模板引擎,具備了渲染頁面的基礎功能,並在其基礎上進行拓展。
而另一個值得關注的是其作者Yehuda Katz,熟悉的朋友可能知道,他是著名JavaScript MVC架構Emberjs代碼的主要貢獻者之一,而且在他的影響下也成為了Emberjs的預設範本引擎。而另外,Yehuda本身也是W3C規範制定小組的成員之一,其影響也不亞於TJ.
拋開架構的背景,我們來看看實際的應用情境。工具無非好壞,順手才是王道。評斷一個東西好壞關鍵還是看它是否滿足自己的應用需求。
在開始做現在的項目之前,我已經用Jade完成了所有的功能,而且對於代碼也還比較滿意。但是在提交之後問題產生了。
因為這個項目不是我一個人在做,和我一起合作的同事之前沒有接觸過Jade,而且另外一位負責編寫樣式的同事對於JavaScript的模板引擎也不是很熟悉。這樣一來,由於我的原因,導致團隊成員之間無法協作。首先是JS開發人員需要時間來掌握和熟悉Jade文法,而另外一個更為嚴重,Jade文法的特性決定了其不利於配套CSS的書寫(這點通過編譯之後可以解決,但是一定程度上增加了工作量)。
於是我開始思考使用Jade是否正確。這裡的兩個問題是我必須面對的,而項目的進度不能因為這個受到影響,於是我開始考慮選擇其他的模板引擎。
前面提到Emberjs用到了Handlebarsjs,所以在選擇時我很容易就想到了它。
Handlebars的官網給出了很多例子,而且上手也很容易,前後端通用,使用起來也很簡單,這裡就不對其使用多做介紹。
回到文章重點,因為Express並不提供對Handlerbarjs的直接支援,這樣在使用時會面臨一定問題。
要在Express中使用Handlerbars作為模板引擎,首先需要做出一下設定:
-
安裝Express, Handlebars, Consolidate:
"dependencies": { "express": "3.x", "consolidate": "0.4.0", "handlebars": "1.0.7"}
-
配置選擇引擎:
// Use handlebars as template engineapp.engine("html", consolidate.handlebars);app.set("view engine", "html");app.set("views", __dirname + "/views");
-
註冊模板:
// Register partialsvar partials = "./views/partials/";fs.readdirSync(partials).forEach(function (file) { var source = fs.readFileSync(partials + file, "utf8"), partial = /(.+)\.html/.exec(file).pop(); Handlebars.registerPartial(partial, source);})
這樣我們就可以在項目中使用Handlerbars來渲染頁面。但是這樣做後,我又遇到了另外一個問題。通過以上的方法我可以很容易的單獨去載入某個頁面。但是實際應用中,一般會有多個頁面,而且多個頁面之間會共用頁面的header和footer部分。這樣會導致重複編寫很多代碼。
在使用Jade是我們可以很容易的使用如下代碼來實現頁面模板功能:
include layout
但是由於Express並非直接支援Handlerbars,所以要實現這個功能還需要一定的設定。在Handlerbars中,可以通過{{> layout }} 來實現sub-template的功能。在尋找了相關模組之後,我發現了hbs這個Express中介軟體。
這個模組使用起來很簡單,可以完美解決我所遇到的問題。使用方法如下:
-
安裝模組:
npm install hbs --save
-
設定模板:
app.set(‘view engine‘, ‘html‘);app.engine(‘html‘, require(‘hbs‘).__express);
-
註冊模板:
var hbs = require(‘hbs‘);hbs.registerHelper(‘helper_name‘, function(...) { ... });hbs.registerPartial(‘partial_name‘, ‘partial value‘);
如果需要註冊整個檔案夾,也可使用如下命令:
var hbs = require(‘hbs‘); hbs.registerPartials(__dirname + ‘/views/partials‘);
這樣,我們就可以做到頁面模板的重複利用,可以顯著減少代碼量。
而另外一個關鍵原因,在於Handlerbars對比Jade,文法更加簡單。最重要的還是其普通元素同樣使用原生HTML的寫法,這樣,對於編寫樣式的同事來講就會更加友好。使用傳統的方式編寫樣式,可以顯著降低學習成本,從而加快項目進度。
而Handerbars所帶來的一些其他功能,也會讓項目的開發變得更加輕鬆。
下面附上我項目的基本結構,希望能對同樣使用這種方案的同學有一定協助。
.├── app.js├── node_modules│ ├── express│ ├── handlebars│ ├── hbs│ ├── less-middleware│ ├── nodemon│ └── request├── package.json├── public│ ├── images│ ├── javascripts│ │ └── app.js│ ├── lib│ │ ├── font│ │ ├── js│ │ └── stylesheets│ └── stylesheets│ ├── style.css│ └── style.less├── routes│ ├── github.js│ └── index.js└── views ├── index.hbs ├── orgs.hbs └── partials ├── footer.hbs └── header.hbs
[轉]Use HandleBars in Express