您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

Node/JavaScript中的模板引擎

时间:2020-10-19 14:03:52  来源:  作者:

简介

在本文中,我们将介绍如何用Node.js和Express来使用 Handlebars 模板引擎。还会介绍什么是模板引擎,以及如何使用把 Handlebars 建服务器端渲染(SSR) web应用程序。

我们还将讨论如何使用 Express.js 框架配置 Handlebars ,以及如何使用内置helpers创建动态页面。最后,我们将了解如何在需要时开发自定义helper 。

什么是模板引擎

早在上世纪90年代,当互联网出现时,它主要用于科学目的,比如发表研究论文,以及作为大学和科学家之间的沟通渠道。那时的大多数网页都是静态的。静态web页面对每个用户都是相同的,不会根据每个用户而改变,如果要更改页面上的任何内容,都必须手动完成。

在现代世界中,事物的互动性更强,并且为每个用户量身定制。今天,几乎每个人都能访问互联网。现在的大多数web应用程序都是动态的。例如,在一些购物网站上,不同用户登录的界面,展示是不一样的,所谓的 千人千面。对于每个人来说,页面将遵循相同的模板(即上面有用户名的连续发布),但是内容将是不同的 。

模板引擎的工作内容:定义展示内容模板,然后根据当前用户和对数据库的查询,用接收到的内容填充模板。

我们可以在后端和前端使用模板引擎。如果我们在后端使用模板引擎来生成html,这种方式叫做服务器端渲染(SSR) 。

Handlebars

Handlebars 在后端和前端模板中都很流行。例如,流行的前端框架Ember就是使用Handlebars作为模板引擎。

Handlebars 是Mustache模板语言的扩展,Mustache 模板语言主要专注于简单性和最小的模板。

在 Node.js 中使用 Handlebars

首先,创建一个空文件夹,然后打开终端,然后运行npm init -y以默认配置建一个空的 Node.js 项目。

开始之前,我们需要安装所需的Node.js库。通过运行以下命令来安装express和express-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/:

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

 

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,运行效果如下:

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

 

向模板传递参数

现在,让我们从页面本身中删除这些硬编码的值,这些值由路由传递进来, 在 app.js 中修改如下内容 :

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

post 对象包含author,image和comments等字段。我们可以在 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>

效果如下:

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

 

使用条件

由于这里需要一些逻辑判断,即 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 为空,所以显示了 期待你们的留言。

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

 

#if是把 Handlebars 的内置帮助器。如果if语句返回true,则将渲染#if块内部的块。如果返回false,undefined,null,"",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来引用当前迭代中的元素。在我们的示例中,它引用了一个随后被渲染的字符串

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

 

如果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。


作者:Janith Kasun 译者:前端小智 来源:stackabuse

原文:https://stackabuse.com/guide-to-handlebars-engine-for-node/



Tags:模板引擎   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
简介在本文中,我们将介绍如何用Node.js和Express来使用 Handlebars 模板引擎。还会介绍什么是模板引擎,以及如何使用把 Handlebars 建服务器端渲染(SSR) web应用程序。我们还...【详细内容】
2020-10-19  Tags: 模板引擎  点击:(68)  评论:(0)  加入收藏
▌简易百科推荐
1、通过条件判断给变量赋值布尔值的正确姿势// badif (a === &#39;a&#39;) { b = true} else { b = false}// goodb = a === &#39;a&#39;2、在if中判断数组长度不为零...【详细内容】
2021-12-24  Mason程    Tags:JavaScript   点击:(5)  评论:(0)  加入收藏
给新手朋友分享我收藏的前端必备javascript已经写好的封装好的方法函数,直接可用。方法函数总计:41个;以下给大家介绍有35个,需要整体文档的朋友私信我,1、输入一个值,将其返回数...【详细内容】
2021-12-15  未来讲IT    Tags:JavaScript   点击:(19)  评论:(0)  加入收藏
1. 检测一个对象是不是纯对象,检测数据类型// 检测数据类型的方法封装(function () { var getProto = Object.getPrototypeOf; // 获取实列的原型对象。 var class2type =...【详细内容】
2021-12-08  前端明明    Tags:js   点击:(23)  评论:(0)  加入收藏
作者:一川来源:前端万有引力 1 写在前面Javascript中的apply、call、bind方法是前端代码开发中相当重要的概念,并且与this的指向密切相关。本篇文章我们将深入探讨这个关键词的...【详细内容】
2021-12-06  Nodejs开发    Tags:Javascript   点击:(19)  评论:(0)  加入收藏
概述DOM全称Document Object Model,即文档对象模型。是HTML和XML文档的编程接口,DOM将文档(HTML或XML)描绘成一个多节点构成的结构。使用JavaScript可以改变文档的结构、样式和...【详细内容】
2021-11-16  海人为记    Tags:DOM模型   点击:(34)  评论:(0)  加入收藏
入口函数 /*js加载完成事件*/ window.onload=function(){ console.log("页面和资源完全加载完毕"); } /*jQuery的ready函数*/ $(document).ready(function(){ co...【详细内容】
2021-11-12  codercyh的开发日记    Tags:jQuery   点击:(35)  评论:(0)  加入收藏
一、判断是否IE浏览器(支持判断IE11与edge)function IEVersion() {var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串var isIE = userAgent.indexOf("comp...【详细内容】
2021-11-02  V面包V    Tags:Javascript   点击:(39)  评论:(0)  加入收藏
Null、Undefined、空检查普通写法: if (username1 !== null || username1 !== undefined || username1 !== &#39;&#39;) { let username = username1; }优化后...【详细内容】
2021-10-28  前端掘金    Tags:JavaScript   点击:(50)  评论:(0)  加入收藏
今天我们将尝试下花 1 分钟的时间简单地了解下什么是 JS 代理对象(proxies)?我们可以这样理解,JS 代理就相当于在对象的外层加了一层拦截,在拦截方法里我们可以自定义一些个性化...【详细内容】
2021-10-18  前端达人    Tags:JS   点击:(51)  评论:(0)  加入收藏
带有多个条件的 if 语句把多个值放在一个数组中,然后调用数组的 includes 方法。// bad if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") { //logic } // be...【详细内容】
2021-09-27  羲和时代    Tags:JS   点击:(58)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条