JavaScript >> Javascript 文檔 >  >> Node.js

如何在 Express.js 中使用 Jade 和 Handlebars

我討厭 Jade,就像許多其他 Node.js 開發人員一樣。但是我發現180有很多功能後我就改了。

在 Storify 和 DocuSign,我們將 Jade 用於一切。我們甚至在瀏覽器中也使用了 Jade。有一個小技巧叫做玉器瀏覽器。它是由 Storify 開發的。我維護了一段時間。

有趣的是,DocuSign 團隊早在遇到我之前就使用了翡翠瀏覽器。他們發誓他們在不知道我參與那個圖書館的情況下僱用了我。 :-)

無論如何,在之前的帖子中介紹了 Jade 和 Handlebars 之後,是時候應用它們來做一些實際的工作了。在這篇文章中,我將介紹:

  • Express.js 4 中 Jade 和 Handlebars 的使用
  • 項目:將 Jade 模板添加到博客

默認情況下,Express.js 4.x(和 3.x)使用​​提供給 res.render 的模板擴展 方法或 view engine 設置的默認擴展名 設置,調用 require__express 模板庫上的方法。換句話說,要讓 Express.js 使用開箱即用的模板引擎庫,該庫需要具有 __express 方法。

當模板引擎庫不提供 __express method 時 , 或類似的 (path , options , callback )參數,建議使用Consolidate.js (https://github.com/visionmedia/consolidate.js/)。

這是 Express.js 4 的 Consolidate.js 的快速示例(版本 4.2.0 和 Consolidate 版本是 0.10.0):

var express = require('express'),
  cons = require('consolidate'),
  app = express()

app.engine('html', cons.swig)

app.set('view engine', 'html')
app.set('views', __dirname + '/views')

var platforms = [
  { name: 'node' },
  { name: 'ruby' },
  { name: 'python' }
]

app.get('/', function(req, res){
  res.render('index', {
    title: 'Consolidate This'
  })
})
app.get('/platforms', function(req, res){
  res.render('platforms', {
    title: 'Platforms',
    platforms: platforms
  })
})

app.listen(3000)
console.log('Express server listening on port 3000')

通常,源代碼在 GitHub 存儲庫中,代碼片段在
ch4/consolidate 文件夾。

有關如何配置 Express.js 設置和使用 Consolidate.js 的更多信息,請參閱 Pro Express.js 4 書(Apress,2014)。

Jade and Express.js

Jade 與 Express.js 開箱即兼容(實際上是默認選擇),因此要使用 Jade 和 Express.js,您只需要安裝模板引擎模塊 Jade(https://www.npmjs.org /package/jade) 並通過 view engine 為 Express.js 提供擴展 設置)。

例如,在主服務器文件中我們設置設置:

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

■ 注意如果你使用$ express <app_name> 命令行工具,可以添加引擎支持選項,即–e EJS 和 –H 的選項 為霍根。這將自動將 EJS 或 Hogan 添加到您的新項目中。如果沒有這些選項中的任何一個,express-generator(4.0.0-4.2.0 版本)將使用 Jade。

在路由文件中,我們可以調用模板——例如,views/page.jade views 文件夾名稱是 Express.js 的另一個默認名稱,可以用
view 覆蓋 設置):

[旁注]

閱讀博客文章很好,但觀看視頻課程更好,因為它們更具吸引力。

許多開發人員抱怨 Node.js 上缺乏負擔得起的高質量視頻材料。觀看 YouTube 視頻會讓人分心,花 500 美元購買 Node 視頻課程很瘋狂!

去看看 Node University,它有關於 Node 的免費視頻課程:node.university。

[旁注結束]

app.get('/page', function(req, res, next){
  //get the data dynamically
  res.render('page', data);
});

如果我們不指定 views engine 設置,則擴展必須顯式傳遞給 res.render()

res.render('page.jade', data);

車把和 Express.js

與 Jade 不同,來自 http://handlebarsjs.com/ 的 Handlebars 庫沒有附帶 __express 方法,但有一些選項可以讓 Handlebars 與 Express.js 一起使用:

  • consolidate :Express.js 模板引擎庫的瑞士軍刀(如上所示)
  • hbs (https://github.com/donpark/hbs):Handlebars 的包裝庫
  • express-Handlebars (file://pchns-f01/TECHNOLOGY/BPR/Techutilities/Apress/Apress%20Outline/express3-handlebars ):儘管有這個名字,這個模塊應該可以在 Express.js 4 和 3.x 版本中正常工作

以下是我們如何使用 hbs 方法(擴展hbs )。在典型的 Express.js 應用程序代碼內部(即,我們使用 $ node 啟動的主文件的配置部分 命令)編寫以下語句:

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

或者,如果另一個擴展名更可取,例如 html ,我們看到以下內容:

...
app.set('view engine', 'html');
pp.engine('html', require('hbs').__express); 
...

express3-handlebars 方法用法如下:

...
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
...

項目:將 Jade 模板添加到博客

最後,我們可以繼續博客。在本節中,我們使用 Jade 添加主頁面,並添加佈局和一些部分:

  • layout.jade :全局應用範圍模板
  • index.jade :包含帖子列表的主頁
  • article.jade :個別文章頁面
  • login.jade :帶有登錄表單的頁面
  • post.jade :添加新文章的頁面
  • admin.jade :登錄後管理文章的頁面

我們將插入 MongoDB 數據庫的演示在 ch5 中 GitHub 存儲庫實用節點的文件夾:https://github.com/azat-co/practicalnode。因此 Jade 模板的源代碼與該 GitHub 項目中的源代碼完全相同。隨意從那裡複製或按照以下說明進行操作。

layout.jade

讓我們在 ch3 中打開我們離開的項目 從 https://github.com/azat-co/practicalnode 並添加 layout.jade 用文檔類型聲明:

doctype html

■ 注意 doctype 5 在 v1.0 左右被棄用。現在我們可以添加頁面的主要標籤了:

html
  head

每個頁面的標題由 appTitle 提供 變量(又名,本地):

title= appTitle

然後,在 head 標籤,我們列出了我們在應用程序範圍內(在每個頁面上)需要的所有前端資產:

script(type="text/javascript", src="js/jquery-2.0.3.min.js")
link(rel='stylesheet', href='https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/css/bootstrap-3.0.2/css/bootstrap.min.css')
link(rel="stylesheet", href="https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/css/bootstrap-3.0.2/css/bootstrap-theme.min.css")
link(rel="stylesheet", href="https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/css/style.css")
script(type="text/javascript", src="https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/css/bootstrap-3.0.2/js/bootstrap.min.js")
script(type="text/javascript", src="https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/js/blog.js")
meta(name="viewport", content="width=device-width, initial-scale=1.0")

主要內容位於 bodyhead 具有相同級別的縮進 :

body

在正文中,我們為稍後添加的樣式編寫了一個 ID 和一些類:

#wrap
  .container

appTitle 值是動態打印的,但 p.lead 元素只有文本:

h1.page-header= appTitle
p.lead Welcome to example from Express.js Experience by&nbsp;
a(href="http://twitter.com/azat_co") @azat_co
|. Please enjoy.

block 部分可以被子模板(擴展此文件的模板)覆蓋:

block page
block header
  div

菜單是存儲在 views/includes 中的部分(即包含) 文件夾。注意沒有引號:

include includes/menu

在這個區塊中,我們可以為用戶顯示消息:

block alert
  div.alert.alert-warning.hidden

主要內容在這個區塊:

.content
  block content

最後,頁腳如下所示:

block footer
  footer
    .container
      p
        | Copyright &copy; 2014 | Issues? Submit to a(href="https://github.com/azat-co/blog-express/issues") GitHub
        | .

layout.jade的完整代碼 如下:

doctype html
html
  head
    title= appTitle
    script(type="text/javascript", src="js/jquery-2.0.3.min.js")
    link(rel="stylesheet", href="https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/css/bootstrap-3.0.2/css/bootstrap.min.css")
    link(rel="stylesheet", href="https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/css/bootstrap-3.0.2/css/bootstrap-theme.min.css")
    link(rel="stylesheet", href="https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/css/style.css")
    script(type="text/javascript", src="https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/css/bootstrap-3.0.2/js/bootstrap.min.js")
    script(type="text/javascript", src="https://m03s6dh33i0jtc3uzfml36au-wpengine.netdna-ssl.com/js/blog.js")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
  body
    #wrap
      .container
        h1.page-header= appTitle
        p.lead Welcome to example from Express.js Experience by&nbsp;
          a(href="http://twitter.com/azat_co") @azat_co
          |. Please enjoy.
        block page
        block header
          div
            include includes/menu
        block alert
          div.alert.alert-warning.hidden
        .content
          block content
    block footer
      footer
        .container
          p
            | Copyright &copy; 2014 | Issues? Submit to
            a(href=" https://github.com/azat-co/blog-express/issues") GitHub
            | .

index.jade

現在我們可以看主頁模板index.jade 擴展佈局:

extends layout

我們設置 menu index 的變量 ,所以菜單包括(即,menu.jade ) 可以確定哪個選項卡顯示為活動:

block page
  - var menu = 'index'

來自locals的文章列表的主要內容 如下:

block content
  if (articles.length === 0)
    | There's no published content yet.
    a(href="/login") Log in
    | to post and publish.
  else
    each article, index in articles
      div
        h2
          a(href="/articles/#{article.slug}")= article.title

index.jade的完整代碼 如下:

extends layout

block page
  - var menu = 'index'
block content
  if (articles.length === 0)
    | There's no published content yet.
    a(href="/login") Log in
    | to post and publish.
  else
    each article, index in articles
      div
        h2
          a(href="/articles/#{article.slug}")= article.title

圖 4-4 顯示了添加樣式表後主頁的外觀。

圖 4-4。主頁

article.jade

單個文章頁面(圖 4-5)相對簡單,因為大部分元素都被抽象為 layout.jade

extends layout

block content
  p
    h1= title
    p= text 

圖 4-5。文章頁面

login.jade

同樣,登錄頁面僅包含一個表單和一個按鈕(帶有 Twitter Bootstrap 類/標記):

extends layout

block page
  - var menu = 'login'

block content
  .col-md-4.col-md-offset-4
    h2 Log in
    div= error
    div
      form(action="/login", method="POST")
        p
          input.form-control(name="email", type="text", placeholder="[email protected]")
        p
          input.form-control(name="password", type="password", placeholder="***")
        p
          button.btn.btn-lg.btn-primary.btn-block(type="submit") Log in
        p
          input.form-control(name="password", type="password", placeholder="***")
        p
          button.btn.btn-lg.btn-primary.btn-block(type="submit") Log in

圖 4–6 顯示了登錄頁面的外觀。

圖 4-6。登錄頁面

post.jade

帖子頁面(圖 4-7)有另一種形式。這一次,表單包含一個文本區域元素:

extends layout
block page
  - var menu = 'post'
block content 
h2 Post an Article
div= error
div.col-md-8
  form(action="/post", method="POST", role="form")
    div.form-group
      label(for="title") Title
      input#title.form-control(name="title", type="text", placeholder="JavaScript is good")
    div.form-group
      label(for="slug") Slug
      input#slug.form-control(name="slug", type="text", placeholder="js-good")
      span.help-block This string will be used in the URL.
    div.form-group
      label(for="text") Text
      textarea#text.form-control(rows="5", name="text", placeholder="Text")
    p
      button.btn.btn-primary(type="submit") Save 

圖 4-7。帖子頁面

admin.jade

管理頁面(圖 4-8)與主頁一樣有一個文章循環。另外,我們可以包含一個前端腳本(js/admin.js ) 特定於該頁面:

extends layout

block page
  - var menu = 'admin'

block content
  div.admin
    if (articles.length === 0 )
      p
        | Nothing to display. Add a new
        a(href="/post") article
        |.
    else

      table.table.table-stripped
        thead
          tr
            th(colspan="2") Actions
            th Post Title
        tbody
          each article, index in articles
            tr(data-id="#{article._id}", class=(!article.published)?'unpublished':'')
              td.action
                button.btn.btn-danger.btn-sm.remove(type="button")
                  span.glyphicon.glyphicon-remove(title="Remove")
              td.action
                button.btn.btn-default.btn-sm.publish(type="button")
                  span.glyphicon(class=(article.published)?"glyphicon-pause":"glyphicon-play",
title=(article.published)?"Unpublish":"Publish")
              td= article.title
      script(type="text/javascript", src="js/admin.js") 

圖 4-8。管理頁面

我們使用插值將文章 ID 打印為屬性 data-id

tr(data-id="#{article._id}", class=(!article.published)?'unpublished':'')

並且,條件(三元)運算符 (https://github.com/donpark/hbs) 用於類和標題屬性。請記住,它是 JavaScript!

                  span.glyphicon(class=(article.published)?"glyphicon-pause":"glyphicon-play",
title=(article.published)?"Unpublish":"Publish") 

總結

您了解了 Jade 和 Handlebars 模板(變量、迭代、條件、部分、取消轉義等),以及如何在獨立的 Node.js 腳本或 Express.js 中使用它們。此外,Blog 的主頁面是使用 Jade 創建的。

在另一個教程中,我們研究了現代 Web 開發和軟件工程的一個重要方面:測試驅動開發。我們查看了 Mocha 模塊,並以真正的 TDD/BDD 風格為 Blog 編寫了一些測試。

將數據庫添加到博客以填充這些模板的示例位於 ch5 https://github.com/azat-co/practicalnode 的。它向您展示瞭如何將 Jade 模板轉換為可工作的 HTML 頁面!


Tutorial JavaScript 教程
  1. 學習nodejs使用grandjs框架速成課程

  2. 使用 aws-lambda-rust-runtime 和 aws-sdk-rust 在 Rust 中編寫 Lambda

  3. 在 2022 年成為更好的前端開發者! 🎆

  4. 設置 iframe 的內容

  5. 永遠不會太晚:從機械工程師到 Web 開發人員

  6. 如何將圖表和圖形添加到 Vue.js 應用程序

  7. 如何在 2020 年學習 React 👩‍💻

  1. 在 Typescript 中合併接口

  2. 顯示多張隨機圖像,而不僅僅是一張

  3. JS Polyfills 在面試中被問到

  4. 使用 React Native 和 Pusher 創建井字遊戲應用

  5. 如何在 VSCode 中運行 React

  6. JS EventListener 動畫結束觸發太早

  7. Javascript Tagalog - 字符串 trimStart 方法

  1. 使用 React 和 HarperDB 構建黑客新聞克隆

  2. Elixir 中的模式匹配

  3. 了解 RxJS Observables 以及為什麼需要它們

  4. 在 JavaScript 中,未定義實際上是未定義的嗎?