Express新手入坑筆記之Handlebars模板繼承

模板繼承,同樣的圓盤, 不同的色彩~
- 續 ofollow,noindex">Express新手入坑筆記之動態渲染HTML ,上一篇只是初步實現了html的動態渲染,但不夠靈活, 如果寫一個動態網站, 會遇到大量模板複用的場景, 為每個url寫一個單獨的html檔案是非常耗時耗力的, 而且可維護性也不好, Handlebars(以下簡稱hbs)為我們提供了繼承模板(類似django的extend)和插入程式碼塊(類似django的include)的方法,下面我來做一個演示
模板佈局的繼承
網站有多個網頁, 網頁的佈局大致相同, 頭部和底部可能是通用的,我們可以為所有網頁設定一個預設的佈局
// 配置模板引擎,設定預設的模板佈局 app.engine('html', exphbs({ layoutsDir: "views/layouts/", defaultLayout: 'layout-header-footer.html', extname: '.html' })); // 根路由對應的頁面, 啟用預設模板佈局 app.get('/', function(req, res) { res.render('index', { title: "首頁", personInfoList: [{ name: "王炮兒(一拳超人)", age: 20 }, { name: "炮姐(御阪美琴)", age: 15 }] }); });
在views資料夾下新建layouts資料夾,在layouts資料夾新建 layout-header-footer.html
作為模板,在 layout-header-footer.html
內寫入以下程式碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{{title}}</title> </head> <body> <style> body{ margin: 0; padding: 0; } </style> <header style="width: 100%; height: 80px; text-align: center; line-height: 80px; background-color: #44A1F8; color: #ffffff;">這是頭部</header> {{{body}}} <footer style="position: fixed; bottom:0;width: 100%; height: 80px; text-align: center; line-height: 80px; background-color: #64B587; color: #ffffff;">這是底部</footer> </body> </html>

views
資料夾下, index.html內的內容精簡(只保留關鍵內容
body
)
<h1 style="color: #64B587">人物介紹</h1> {{#each personInfoList}} <h2>暱稱:{{this.name}}</h2> <h2>年齡:{{this.age}}</h2> <hr> {{/each}}
- 重新訪問根路由

有些網頁可能比較特別, 只需要顯示通用的底部
- 在layouts資料夾內,新建
layout-footer.html
作為模板(顧名思義, 與上面的通用模板,layout-header-footer.html
相比,layout-footer.html
只有底部內容),layout-footer.html
內的內容為:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{{title}}</title> </head> <body> <style> body{ margin: 0; padding: 0; } </style> {{{body}}} <footer style="position: fixed; bottom:0;width: 100%; height: 80px; text-align: center; line-height: 80px; background-color: #64B587; color: #ffffff;">只有底部</footer> </body> </html>

- 編寫
/about
路徑的處理函式, 讓/about
對應的網頁套用layout-footer.html
模板
// 匹配/about路由 app.get('/about', function(req, res) { res.render('about', { layout: "layout-footer.html" }); });
- 在views下,編寫
about.html
檔案
<h1>關於</h1>

- 訪問
http://localhost:3000/about
, 效果如圖所示

預設模板佈局
和
個性化模板佈局
的編寫和使用, 但在實際開發中, 我可能會遇到在某個頁面內,引入程式碼塊的需求, 比如插入廣告位! 下面我們來完成引入廣告位的例項~
引入程式碼塊
需求: 引入廣告位
- 在
views
資料夾下新建partials
資料夾,在partials
內新建ad.html
,在ad.html
內編寫廣告程式碼

<div style="width: 100%; height: 20px; text-align: center; font-size: 12px; line-height: 20px; color: #413F43; background-color: #F0BB40;">這是一段廣告</div>
- 在express-simple-server.js中配置
廣告程式碼所在的目錄

// 配置模板引擎 app.engine('html', exphbs({ +partialsDir: 'views/partials/', layoutsDir: "views/layouts/", defaultLayout: 'layout-header-footer.html', extname: '.html' }));
- 修改abou.html,插入廣告程式碼

<h1>關於</h1> {{>ad}}
- 檢視插入效果

- express-simple-server.js最終程式碼
const express = require('express'); const exphbs = require('express-handlebars'); const app = express(); // 配置模板引擎 app.engine('html', exphbs({ partialsDir: 'views/partials/', layoutsDir: "views/layouts/", defaultLayout: 'layout-header-footer.html', extname: '.html' })); app.set('view engine', 'html'); // 如果在環境變數內, 設定了程式執行埠,則使用環境變數設定的埠號, 否則使用3000埠 app.set('port', process.env.PORT || 3000); // 匹配靜態檔案目錄 app.use(express.static(__dirname + '/public')); // 匹配根路由 / (如果不特別指明返回的狀態碼, 則預設返回200) app.get('/', function(req, res) { res.render('index', { title: "首頁", personInfoList: [{ name: "王炮兒(一拳超人)", age: 20 }, { name: "炮姐(御阪美琴)", age: 15 }] }); }); // 匹配/about路由 app.get('/about', function(req, res) { res.render('about', { layout: "layout-footer.html" }); }); // 定製 404 頁面 (返回404狀態碼) app.use(function(req, res) { let currentTime = new Date(); res.type('text/plain'); res.status(404); res.send('404 - 你訪問的頁面可能去了火星\n' + currentTime); }); //定製 500 頁面 (返回500狀態碼) app.use(function(err, req, res, next) { let currentTime = new Date(); let errInfo = err.stack; res.type('text/plain'); res.status(500); res.send('500 - 伺服器發生錯誤\n' + 'errInfo:' + errInfo + '\n' + 'currentTime:' + currentTime); }); // 監聽服務埠, 保證程式不會退出 app.listen(app.get('port'), function() { console.log('Express 服務正在執行在 http://localhost:' + app.get('port') + '; 按 Ctrl-C 關閉服務.'); })
小結:
如果你瞭解django的模板繼承(extend)和程式碼插入(include)的規則,會發現hbs也是類似的, 其實hbs還有名為helper的玩法, 可以更加靈活插入css, js, html,有興趣可以自己瞭解下,或者等我後續的更新