【Nodejs】淺談網頁開發中的模板語言:Pug 和 EJS

2023/08/29閱讀時間約 18 分鐘

這一篇文章,我想來談談模板語言(template language/engine)。而其中比較有名的為handlebar、pug、ejs。那我會的事後兩著,因此拿這兩個出來寫一篇文章。

Pug

指令:npm install pug
raw-image

比起 HTML 的語法,pug 語法可以說簡潔很多。

那下面直接放一個html跟一個pug

// shop.html 
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商城</title>
<link rel="stylesheet" href="/css/bootstrap.min.css" />

</head>

<body>
<header class="main-header">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="/">NodeJs商城</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="/">商城</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/admin/add-product">添加产品</a>
</li>

</ul>
</div>
</nav>

</header>

<main class="container p-5">
<h1>我的产品</h1>
<div class="row">
<div class="col-md-4 p-2">
<div class="card" style="width: 18rem;">
<img src="https://miro.medium.com/max/1200/1*m5RYM_Wkj4LsZewpigV5tg.jpeg" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">产品名称</h5>
<p class="card-text">产品详情介绍信息,该课程讲解十分细致,各个知识点都有所涉及。</p>
<p>29.99</p>
<a href="#" class="btn btn-primary">加入购物车</a>
</div>
</div>

</div>
</div>
</main>
</body>

</html>
// shop.pug
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title #{docTitle}
link(rel="stylesheet", href="/css/bootstrap.min.css")
body

nav.navbar.navbar-expand-lg.navbar-dark.bg-dark
a.navbar-brand(href="/") NodeJs商城
button.navbar-toggler(type="button", data-toggle="collapse",data-target="#navbarNav" ,aria-controls="navbarNav" ,aria-expanded="false",
aria-label="Toggle navigation")
span.navbar-toggler-icon
div#navbarNav.collapse.navbar-collapse
ul.navbar-nav
li.nav-item
a.nav-link(href="/") 商城
li.nav-item.active
a.nav-link(href="/admin/add-product") 添加产品

main.container.p-5
h1 我的产品
if prods.length > 0
div.row
each product in prods
div.col-md-4.p-2
div.card(style="width: 18rem;")
img.card-img-top(src="https://miro.medium.com/max/1200/1*m5RYM_Wkj4LsZewpigV5tg.jpeg",alt="产品图片")
div.card-body
h5.card-title #{product.title}
p.card-text 产品详情介绍信息,该课程讲解十分细致,各个知识点都有所涉及。
p ¥29.99
a.btn.btn-primary(href="#") 加入购物车
else
div.alert.alert-danger(role="alert") 暂无产品

恩...他好像有一種python的感覺(笑)。

附上html轉pug得線上工具:https://pughtml.com

pug使用動態網頁

那大概知道pug的代碼風格後,要來提到動態網頁的部分了。恩...可能我是小菜雞的緣故,目前碰到的還是以字串、變數或陣列為主。

先來看一下這一段js代碼:

// adminData 為一個array
const adminData = require("./admin");

router.get("/", (req, res, next) => {
const products = adminData.products;
// 要傳出去的東西
res.render("shop", { prods: products, docTitle: "商城" });
});

module.exports = router;

我在這一段代碼中主要傳兩個東西,一個是陣列prods,一個是字串docTitle,那傳到的位置為shop.pug(笑死我剛剛打成png,圖然感覺這個單字好可愛,一定是我打錯的部分)

接著來看png的地方吧

// 傳遞字串這樣寫
title #{docTitle}

// 陣列的話主要是要一個一個輸出,這邊要使用each...in...
each product in prods
div.col-md-4.p-2
div.card(style="width: 18rem;")
img.card-img-top(src="https://miro.medium.com/max/1200/1*m5RYM_Wkj4LsZewpigV5tg.jpeg",alt="产品图片")
div.card-body
h5.card-title #{product.title}
p.card-text 产品详情介绍信息,该课程讲解十分细致,各个知识点都有所涉及。
p ¥29.99
a.btn.btn-primary(href="#") 加入购物车

Include的方式去封裝pug

在每一次轉html轉pug的時候,是不是有一些東西會重複寫(沒錯~),而工成師的經隨就是:懶!!!(不是我說的,是我們老師說的!!!),因此我們可以使用include的方式去封裝pug

要封裝的部分用一個開一個位置給他

// includes/header.pug 
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title #{docTitle}
link(rel="stylesheet", href="/css/bootstrap.min.css")

接著在每一個需要用到它的地方:

include includes header.pug 
... 其他代碼



EJS(Embedded JavaScript templates)

用於在Node.js應用程式中生成動態HTML內容。它允許你將JavaScript嵌入到HTML中,從而可以根據資料動態生成HTML內容。

指令: npm install ejs
設定:要在你的伺服器上加上這兩行
app.set('view engine', 'ejs');
app.set('views', 'views');

那ejs我是把它區分成三種,照理來說是混搭使用,那為了清楚展示,我故意差開寫:

  1. <% js條件 %> 在裡面寫js的條件判斷式
<!DOCTYPE html>
<html>
<head>
<title>Conditional Example</title>
</head>
<body>
<% if (showMessage) { %>
<h1>Message is shown!</h1>
<% } else { %>
<h1>Message is not shown!</h1>
<% } %>
</body>
</html>
  1. <%= title %> 後台有東西要傳入,加等號
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h1><%= message %></h1>
</body>
</html>
  1. <%- %> 類似pug的封裝
<!DOCTYPE html>
<html>
<head>
<title>Unescaped Content Example</title>
</head>
<body>
<div>
<h1>Unescaped Content Example</h1>
<div class="content">
<%- htmlContent %>
</div>
</div>
</body>
</html>

<%- htmlContent %> 裡面就是裝載著封裝的html

這樣的方式也可以用在express框架的router

app.get('/', (req, res) => {
const htmlContent = '<p>This is <strong>unescaped</strong> content.</p>';
res.render('unescaped', { htmlContent });
});

🥰那~~以上是本文所分享的內容。如果您發現任何錯誤或遺漏,請不吝賜教。

3會員
10內容數
留言0
查看全部
發表第一個留言支持創作者!