HTML 模板是一种允许我们创建基本 HTML 结构并使用占位符根据从 JSON 文件或数据库中检索到的数据动态生成内容的技术。
让我们考虑一个假设实例,其中我们的网站包含许多产品卡,每个卡都包含从 JSON 文件中检索到的特定产品详细信息。
现在,如果我们要从 JSON 文件中添加或删除任何产品,我们将如何在前端动态更新相应的卡片?
考虑到我们基于内容的数据存储在 JSON 文件中,我们可以继续从现有的 HTML 代码创建可重用的模板。
第 1 步:构建模板
作为开发人员,您可能熟悉提供动态 Web 内容的概念。实现这一目标的一种方法是使用模板。
我们将创建两个 HTML 模板,一个用于产品概览页面,一个用于单个产品卡片。
第一个模板template-card.html
用作单个产品卡片的蓝图,第二个模板template-overview.html
用作概览页面的蓝图。这些模板包含占位符,当用户请求页面时,这些占位符将被替换为实际内容。
确保您的占位符不包含任何属于 HTML 代码的符号。占位符的常用语法是{%PLACEHOLDER_NAME%}
.
这是template-card.html
我们的第一个模板,用作根据需要动态创建尽可能多的卡片的蓝图。
<figure class="card">
<div class="card__emoji">{%IMAGE%}{%IMAGE%}</div>
<div class="card__title-box">
<h2 class="card__title">{%PRODUCTNAME%}</h2>
</div>
<div class="card__details">
<div class="card__detail-box">
<h6 class="card__detail card__detail
{%NOT_ORGANIC%}"> Organic!</h6>
</div>
<div class="card__detail-box">
<h6 class="card__detail">{%QUANTITY%} per 📦</h6>
</div>
<div class="card__detail-box">
<h6 class="card__detail card__detail--price">
{%PRICE%}€</h6>
</div>
</div>
<a class="card__link" href="/product?id={%ID%}">
<span>Detail <i class="emoji-right">👉</i></span>
</a>
</figure>
由于此卡片将用作模板,因此其中包含的信息也应替换为占位符。添加占位符后,卡片将类似于以下内容:
<figure class="card">
<div class="card__emoji">🥦🥦</div>
<div class="card__title-box">
<h2 class="card__title">Apollo Broccoli</h2>
</div>
<div class="card__details">
<div class="card__detail-box">
<h6 class="card__detail card__detail--organic">Organic!</h6>
</div>
<div class="card__detail-box">
<h6 class="card__detail">3🥦 per 📦</h6>
</div>
<div class="card__detail-box">
<h6 class="card__detail card__detail-
price">5.50€</h6>
</div>
</div>
<a class="card__link" href="/product?id=">
<span>Detail <i class="emoji-right">👉</i></span>
</a>
</figure>
锚标记包含一个 href 链接,其中包含一个 ID 的占位符。这表明我们的 JSON 文件中的每张卡或产品都有一个不同的 ID。这些 ID 是唯一的,将用于在路由过程中识别每个产品。
此外,当我们需要根据元素的类别设置元素样式时,CSS 类和 ID 可以用占位符代替,就像在图像示例中所做的那样。这种方法在这种情况下特别有用。
<body>
<div class="container">
<h1>🌽 Node Farm 🥦</h1>
<div class="cards-container">
{%PRODUCT_CARDS%}
</div>
</div>
</body>
在此示例中,我们已将模板卡片替换为占位符。请务必记住,我们将使用这个单一模板卡片动态生成多张卡片。
注意:这是我们的第二张模板卡,template-overview.html
第 2 步:填充模板
有趣的部分来了,通过用实际内容替换我们的占位符来填充我们的模板。
当用户请求 URL 时,代码会同步读取相关模板文件(或者template-overview.html
或template-card.html
),用 JSON 文件中的内容动态填充它,并将相关内容作为响应发回给用户。
这是通过使用函数实现的replaceTemplate
,该函数用实际内容替换模板中的占位符。
// SECOND STEP:
const replaceTemplate = (temp, product) => {
let output = temp.replace(/{%PRODUCTNAME%}/g, product.productName);
output = output.replace(/{%IMAGE%}/g, product.image);
output = output.replace(/{%PRICE%}/g, product.price);
output = output.replace(/{%ID%}/g, product.id);
// /g is a regex global flag
return output;
}
// FIRST STEP:
const tempOverview = fs.readFileSync(`${__dirname}/templates/template-overview.html`, 'utf-8');
const tempCard = fs.readFileSync(`${__dirname}/templates/template-card.html`, 'utf-8');
const data = fs.readFileSync(`${__dirname}/dev-data/data.json`, 'utf-8');
const dataObj = JSON.parse(data);
// THIRD STEP:
const server = http.createServer((req, res) => {
const pathName = req.url;
//FOURTH STEP:
//Here is the Overview
if(pathName === '/' || pathName === '/overview') {
res.writeHead(200, {'Content-type': 'text/html'});
const cardsHtml = dataObj.map(el => replaceTemplate(tempCard, el)).join('');
const output = tempOverview.replace('{%PRODUCT_CARDS%', cardsHtml);
res.end(output);
//API
} else if(pathName === '/api') {
res.writeHead(200, {'Content-type': 'application/json'});
res.end(data);
// Not Found
} else {
res.writeHead(404, {
'Content-type': 'text/html', //standard header
'my-header': 'hello-world'
});
res.end('<h1>This page cannot be found.</h1>');
}
});
server.listen(8000, '127.0.0.1', () => {
console.log('Listening to requests on port 8000');
});
res.writeHead(404, {
'Content-type': 'text/html', //standard header
'my-header': 'hello-world'
});
res.end('<h1>This page cannot be found.</h1>');
}
});
server.listen(8000, '127.0.0.1', () => {
console.log('Listening to requests on port 8000');
});
别担心,我们将仔细研究上面的大块代码,并用更简单的术语弄清楚它的作用。
- 首先,读取两个 HTML 模板文件和存储在 JSON 文件中的产品数据
- 其次,定义一个函数,用特定于产品的数据替换模板中的占位符。在这里,我们的函数被命名为
replaceTemplate
- 第三、监听传入的 HTTP 请求并检查请求 URL 的路径名
- 第四,如果路径名为
/
或/overview
,则使用replaceTemplatefunction
和JSON文件中的产品数据替换tempCard
模板中的占位符,为每个产品卡生成HTML代码。 - 然后连接每张卡片的结果 HTML 以创建字符串cardsHtml。然后修改模板
tempOverview
以包含cardsHtml
字符串,并将生成的 HTML 代码作为响应发回。 - 此外,如果路径名是,/api它会以 JSON 格式发回产品数据作为响应
- 最后,如果路径名是其他任何内容,则发回 404 错误消息。
哇,那段代码看起来确实很多,但如果我们仔细看,一步一步来,它并没有那么复杂。
它所做的只是用真实信息替换一些特殊词并将其发送回网站,以便人们可以看到它!
HTML 模板的好处
HTML 模板提供了几个好处,使其成为 Web 开发人员的热门选择:
- 通过使用 HTML 模板,我们将内容与表示分离,允许开发人员生成可重复使用的模板,这些模板可以处理来自多个来源的不同数量的数据,并维护类似代码的多个副本。
- HTML 模板为呈现数据、改善用户体验和轻松导航站点提供了标准结构。
- 模板的灵活性使得修改底层数据变得更加容易。这节省了时间和精力,因为开发人员不需要手动更改 HTML 代码。
- 由于 HTML 模板可重复使用,因此更易于维护和更新。可以在不修改模板代码的情况下对基础数据进行更改,从而降低出错的可能性。
- HTML 模板可以在不影响性能的情况下处理大量数据。这使其成为具有大量动态内容的网站的理想选择。
总之,HTML 模板是一种高效、一致、灵活且可扩展的技术,可简化动态 Web 内容的开发和维护。
通过将内容与表示分离,HTML 模板使开发人员能够创建可重用的模板,这些模板可以处理不同数量的数据,而无需将内容硬编码到每个页面中。
拓展部分:
Node.js 中还有其他几个可用的模板引擎,例如 EJS、Pug(以前称为 Jade)、Handlebars 和 Mustache 等。
要在 Node.js 中使用模板引擎,您需要通过 npm 安装它,然后在您的代码中需要它。这些引擎提供了一种通过将数据插入模板内的占位符来生成 HTML 的方法。