入門指南:Node/JavaScript中的模板引擎

做者:Janith Kasun
譯者:前端小智
來源:stackabuse

有夢想,有乾貨,微信搜索 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。html

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及個人系列文章。前端

簡介

在本文中,咱們將介紹如何用Node.jsExpress來使用 Handlebars 模板引擎。還會介紹什麼是模板引擎,以及如何使用把 Handlebars 建服務器端渲染(SSR) web應用程序。node

咱們還將討論如何使用 Express.js 框架配置 Handlebars ,以及如何使用內置helpers 建立動態頁面。最後,咱們將瞭解如何在須要時開發自定義helper ?。git

什麼是模板引擎

早在上世紀90年代,當互聯網出現時,它主要用於科學目的,好比發表研究論文,以及做爲大學和科學家之間的溝通渠道。那時的大多數網頁都是靜態的。靜態web頁面對每一個用戶都是相同的,不會根據每一個用戶而改變,若是要更改頁面上的任何內容,都必須手動完成。github

在現代世界中,事物的互動性更強,而且爲每一個用戶量身定製。今天,幾乎每一個人都能訪問互聯網。如今的大多數web應用程序都是動態的。例如,在一些購物網站上,不一樣用戶登陸的界面,展現是不同的,所謂的 千人千面。對於每一個人來講,頁面將遵循相同的模板(即上面有用戶名的連續發佈),可是內容將是不一樣的 ?。web

模板引擎的工做內容:定義展現內容模板,而後根據當前用戶和對數據庫的查詢,用接收到的內容填充模板。面試

咱們能夠在後端和前端使用模板引擎。若是咱們在後端使用模板引擎來生成HTML,這種方式叫作服務器端渲染(SSR) ?。數據庫

Handlebars

Handlebars 在後端和前端模板中都很流行。例如,流行的前端框架Ember就是使用Handlebars做爲模板引擎。express

Handlebars 是Mustache模板語言的擴展,Mustache 模板語言主要專一於簡單性和最小的模板。npm

在 Node.js 中使用 Handlebars

首先,建立一個空文件夾,而後打開終端,而後運行npm init -y以默認配置建一個空的 Node.js 項目。

開始以前,咱們須要安裝所需的Node.js庫。 經過運行如下命令來安裝expressexpress-handlebars模塊:

npm install --save express express-handlebars

注意:在服務器端使用 Handlebars 時,你可能會使用一個像express-handlebars這樣的幫助模塊,它將Handlebars與web框架集成在一塊兒。在本文中,咱們主要關注模板語法,這也是咱們使用express-handlebars的緣由,可是若是你本身處理模板編譯和渲染,還須要看 compilation API reference 對應的文檔說明 ?。

而後,從新建立默認的 Handlebars 目錄結構。 views 文件夾包含全部Handlebars 手模板:

├── app.js
└── views
    ├── home.hbs
    └── layouts
        └── main.hbs

views文件夾內的layouts文件夾將包含佈局或模板包裝器。 這些佈局將包含模板之間共享的HTML結構,樣式表和腳本。

main.hbs文件是主佈局,home.hbs文件是咱們要構建的示例Handlebars模板。

在咱們的示例中,咱們使用一個腳原本保持簡單性。首先,在app.js文件中導入所需的庫:

const express = require('express');
const exphbs = require('express-handlebars');

而後,建立一個Express app

const app = express();

如今,咱們能夠配置express-handlebars做爲咱們的視圖引擎:

const express = require('express');
const exphbs = require('express-handlebars');


const app = express();

app.engine('hbs', exphbs({
  defaultLayout: 'main',
  extname: '.hbs'
}))

app.set('view engine', 'hbs');

默認狀況下,Handlebars 模板的擴展名是.handlebars。 可是在這裏的設置中,咱們經過extname標誌將其更改成.hbs,由於它更短。

接着,在main.hbs佈局添加Bootstrap腳本和樣式:

home.hb添加以下內容:

<h1>Hello World from Handlebars</h1>

app.js 中添加對應的路由配置:

app.get('/', (req, res) => {
    res.render('home');
});

而後,添加若是監聽的端口號:

app.listen(3000, () => {
    console.log('The web server has started on port 3000');
});

這樣就能夠在控制檯中運行node app.js啓動應用程序。

可是咱們也能夠選擇使用諸如nodemon之類的工具。 使用nodemon,咱們在改代碼時不須要每次都要從新啓動服務器,nodemon會自動刷新服務器。

盤它:

npm i -g nodemon

安裝後,運行:

nodemon app.js

在瀏覽器中打開 http://localhost:3000/

clipboard.png

Handlebars 更多功能

爲了展現一些Handlebars功能,咱們將構建一個社交媒體類的網站。 這裏咱們用一個簡單的數組來模擬數據庫。

home.hbs內容更新成以下:

<nav class="navbar navbar-dark bg-dark">
    <a class="navbar-brand" href="#">Book Face</a>
</nav>

<div class="posts">
    <div class="row justify-content-center">
        <div class="col-lg-7" style="margin-top: 50px;">
            <div class="card">

                <img src="https://picsum.photos/500/500"
                    class="card-img-top" alt="...">
                <div class="card-body">
                    <h5 class="card-title">此文章由 前端小智 發佈</h5>

                    <ul class="list-group">
                        <li class="list-group-item">期待大家的留言/li>
                        <li class="list-group-item">期待大家的留言</li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>

上面咱們添加了一個 navbar 和一個帖子的展現內容 card,運行效果以下:

clipboard.png

向模板傳遞參數

如今,讓咱們從頁面自己中刪除這些硬編碼的值,這些值由路由傳遞進來, 在 app.js 中修改以下內容 :

app.get('/', function (req, res) {
    res.render('home', {
        post: {
            author: '小智',
            image: 'https://picsum.photos/500/500',
            comments: []
        }
    });
});

post 對象包含author,imagecomments等字段。 咱們能夠在 Handlebars模板使用{{post}}來引用這些值:

<nav class="navbar navbar-dark bg-dark">
    <a class="navbar-brand" href="#">Book Face</a>
</nav>

<div class="posts">
    <div class="row justify-content-center">
        <div class="col-lg-7" style="margin-top: 50px;">
            <div class="card">

                <img src="https://picsum.photos/500/500"
                    class="card-img-top" alt="...">
                <div class="card-body">
                    <h5 class="card-title">此文章由 {{post.author}} 發佈</h5>

                    <ul class="list-group">
                        <li class="list-group-item">期待大家的留言/li>
                        <li class="list-group-item">期待大家的留言</li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>

效果以下:

clipboard.png

使用條件

因爲這裏須要一些邏輯判斷,即 comments 沒數據不顯示,咱們看看如何在Handlebars 模板中使用條件:

<nav class="navbar navbar-dark bg-dark">
    <a class="navbar-brand" href="#">Book Face</a>
</nav>

<div class="posts">
    <div class="row justify-content-center">
        <div class="col-lg-7" style="margin-top: 50px;">
            <div class="card">

                <img src="https://picsum.photos/500/500"
                    class="card-img-top" alt="...">
                <div class="card-body">
                    <h5 class="card-title">此文章由 {{post.author}} 發佈</h5>
                    {{#if post.comments}}
                    <ul class="list-group">
                    </ul>
                    {{else}}
                    <ul class="list-group">
                        <li class="list-group-item">期待大家的留言</li>
                    </ul>
                    {{/if}}
                </div>
            </div>
        </div>
    </div>
</div>

這裏咱們的 comments 爲空,因此顯示了 期待大家的留言

clipboard.png

#if是把 Handlebars 的內置幫助器。 若是if語句返回true,則將渲染#if塊內部的塊。 若是返回falseundefinednull""0[],則不會渲染該塊。

#if僅接受一個條件,而且不能使用 JS 比較語法(===)。 若是須要使用多個條件或其餘語法,則能夠在代碼中建立一個變量,而後將其傳遞給模板。 另外,你能夠定義本身的 helper ,咱們將在上一節中進行操做。

使用循環

因爲帖子能夠包含多個評論,所以咱們須要一個循環渲染它們。 首先,咱們先添加一些數據:

app.get('/', function (req, res) {
  res.render('home', {
      post: {
          author: '小智',
          image: 'https://picsum.photos/500/500',
          comments: [
            '前端小智終身學習者',
            '前端小智持續分享者',
            '雖然沒啥流量,但也但願你也能堅持分享下去,幫助更多的初學者 ?'
          ]
      }
  });
});

如今,在咱們的模板中,使用#each循環遍歷它們:

<nav class="navbar navbar-dark bg-dark">
    <a class="navbar-brand" href="#">Book Face</a>
</nav>

<div class="posts">
    <div class="row justify-content-center">
        <div class="col-lg-7" style="margin-top: 50px;">
            <div class="card">

                <img src="https://picsum.photos/500/500"
                    class="card-img-top" alt="...">
                <div class="card-body">
                    <h5 class="card-title">此文章由 {{post.author}} 發佈</h5>
                    {{#if post.comments}}
                    <ul class="list-group">
                      {{#each post.comments}}
                      <li class="list-group-item">{{this}}</li>
                      {{/each}}
                    </ul>
                    {{else}}
                    <ul class="list-group">
                        <li class="list-group-item">期待大家的留言</li>
                    </ul>
                    {{/if}}
                </div>
            </div>
        </div>
    </div>
</div>

#each循環中,可使用this來引用當前迭代中的元素。在咱們的示例中,它引用了一個隨後被渲染的字符串

clipboard.png

若是posts是一個對象數組,你也能夠訪問該對象的任何屬性。例如,若是有一我的員數組,你能夠簡單地使用this.name來訪問name字段。

如今,爲咱們的 posts 添加多個數據:

app.get('/', function (req, res) {
  res.render('home', {
      posts: [
        {
          author: '小智',
          image: 'https://picsum.photos/500/500',
          comments: [
            '前端小智終身學習者',
            '前端小智持續分享者',
            '雖然沒啥流量,但也但願你也能堅持分享下去,幫助更多的初學者 ?'
          ]
        },
        {
          author: '前端大智',
          image: 'https://picsum.photos/500/500?2',
          comments: []
        }
      ]
  });
});

而後,使用#each來遍歷 posts

<div class="posts">
    <div class="row justify-content-center">
      {{#each posts}}
        <div class="col-lg-7" style="margin-top: 50px;">
            <div class="card">
                <img src="{{this.image}}" class="card-img-top" alt="...">
                <div class="card-body">
                    <h5 class="card-title">此文章由 {{post.author}} 發佈</h5>
                    {{#if this.comments}}
                    <ul class="list-group">
                      {{#each this.comments}}
                      <li class="list-group-item">{{this}}</li>
                      {{/each}}
                    </ul>
                    {{else}}
                    <ul class="list-group">
                        <li class="list-group-item">期待大家的留言</li>
                    </ul>
                    {{/if}}
                </div>
            </div>
        </div>
      {{/each}}
    </div>
</div>

總結

在本文中,咱們介紹了Handlebars的基礎知識,Handlebars 是Node.js 和前端JavaScript 的模板引擎。 使用 Handlebars,咱們能夠建立在服務器端或客戶端渲染的動態網頁。 使用 Handlebars 的條件,循環,局部和自定義幫助器功能,咱們的網頁將不只僅是靜態HTML。


代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

原文:https://stackabuse.com/guide-...

交流

文章每週持續更新,能夠微信搜索【大遷世界 】第一時間閱讀,回覆【福利】有多份前端視頻等着你,本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,歡迎Star。

相關文章
相關標籤/搜索