前言
在 Node.js 开发中,应用程序与前端界面的交互需要通过模板引擎实现。而 Express.js 框架中的 express-handlebars 模板引擎既可以方便地实现模板渲染,又可以达到前后端分离的效果。本文将介绍如何使用 npm 包 @types/express-handlebars 来优化 TypeScript 代码的编写,从而避免出现类型模糊或错误等问题。
环境设置
如果您希望在 TypeScript 代码中使用 express-handlebars 模板引擎,需要安装添加额外的声明类型支持。此时,npm 包 @types/express-handlebars 就能够发挥重要作用,它提供了语法提示和类型检查等功能,从而节省了调试时间。
使用 npm 安装 @types/express-handlebars:
npm install --save-dev @types/express-handlebars
基本用法
引入 @types/express-handlebars 后,我们就可以在 TypeScript 中使用 express-handlebars 模板引擎。下面将介绍两个基本用法:
用法 1:创建 express-handlebars 实例
当使用 express-handlebars 作为模板引擎时,需要使用 express-handlebars 构造函数来创建实例。@types/express-handlebars 提供了多个构造函数的类型定义,最常用的是如下形式:
-- -------------------- ---- ------- ------ ------ ---- -------------------- ----- ------- - - -------------- ------- -------- ------ - ----------------- ---------------- ------------- -------- ------
用法 2:在视图中使用 express-handlebars
view(视图)是 express-handlebars 的一个重要组成部分,视图可以引用 handlebars 模板文件,用于生成应用程序中需要的 HTML 标记。为了使用视图组件,需要在 app.set() 函数中添加一个属性:
app.set('views', path.join(__dirname, 'views'))
__dirname
表示当前文件所在的路径。
当配置视图文件夹后,就可以在路由处理程序中调用 response.render()
方法,向模板传递信息。
如下面的示例:
import { Request, Response } from 'express' export function homeRoute (req: Request, res: Response) { res.render('home', { title: 'Home Page' }) }
进阶用法
在上面的例子中,我们提供了一个可行的 TypeScript 实现,它所需的包括 express-handlebars 模板引擎,Express.js 服务器和 TypeScript 编译器。现在我们来尝试对其进行优化。这标志着我们要开始考虑应用程序的整体结构和运行方式,以及它的目标和抽象层次。
使用 Partial 将依赖注入视图中
在实际开发中,您的组件通常需要访问其他服务,例如数据库、缓存或其它 REST API。如果代码在所有代码中直接访问这些接口,就会产生严重的耦合。因此,我们必须将关注点分离出来,使用插入注入将关注点从相关组件中分离。
从实践角度来看,习惯使用 express-handlebars 的开发人员通常以这种方式封装它们:
// hbs.js const exphbs = require('express-handlebars') const hbs = exphbs.create() module.exports = hbs
通过这个例子,我们可以看到,在 hbs.js 文件中,我们首先引入了 express-handlebars 模块,然后使用它的 create() 方法创建了一个标准的 handlebars 实例。最后,我们导出了该实例,以便将其注入到应用程序的其他部分中。
显然,使用 Partial 要更加方便,因为他们通过代码检查和 IDE 提示可用于类型注释和翻译。因此,我们编辑 @types/express-handlebars 的 index.d.ts 文件,定义 Partial 类型后,代码将直接和 handlebars 全局 Hbs 对象相互转换,这让我们维护了可靠的代码留下的极佳的体验。
-- -------------------- ---- ------- -- ------------------------------------ ------- ------ - --------- ------- - --------- ----------- - ------- -------- - --------- -------- - ------------ ------- --------- ------- ---------- ---------- ----- - - - ------ - -- ------ ---- -------------------- ------- ------ - --------- --- - ---- -------------- - -------------------- - - --------- ------- ------------ ------- --------------- ------- ------------- ------ - --------- --------- ---------------------- ----------------- ------ - ---- ------------ - ------ ---- ----------------- - ------ ---- -------------------- ------- ------ - --- - - -- -- ----- -------- --------- - - ----------------- - ------------ --------- ----------- - ------- ------------- ------------- ------- -------- --------- ------- ----- ---------------------- --------- ----- ----- - ----- ------ ------- -- ---- -- ---- - - - ------- -------- ---------- - ----- -------- -------- ------------------ -- --------------- ------ - ----------
分离视图和控制器
我们考虑 MVC 的描述于是就会有它们各自的角色定义:Model(模型)、View(视图)和 Controller(控制器)。大多数 IDE 都提供了文件模板,可以帮助您毫不费力地生成这些模型。这也就是 Express generator 工具所做的事情。但是,如果你愿意,你也可以手动创建这些模板。这样可以更好地了解整体应用的功能和结构。
下面是一个简单的控制器示例,它处理用户注册表单的提交:
-- -------------------- ---- ------- ------ - -------- -------- - ---- --------- ------ -------- -------- ----- -------- ---- --------- - ----- ---- - -------- -- ----------- -- ------------- -- -------------- - -- ---- ------ ---- ---- -- -------- --------------------- - ---- - ------------------- - -------- ---------- ---- ------- -- - -
这个控制器很简单,它检查了一个 POST 请求是否包含必需的数据,并在数据有效时向模板返回成功消息,否则返回错误消息。现在,让我们看看视图如何被触发的。
使用 Layouts 与 Partials 改善应用性能
在 Express.js 中,浏览器代码(HTML、CSS、JavaScript)都是通过路由处理程序来渲染的。这些路由通常由控制器调用。当控制器处理成功时,它会直接发送 HTML 模板到浏览器。此过程用于生成动态内容,然后通过所谓的视图。
使用 Express.js 模板渲染不仅可以提高开发效率,还可以改善应用程序的性能。当然,提高应用程序性能的关键是把模板文件转换成 JavaScript 代码。这样一来,模板可以在服务端被执行而不需要在浏览器端进行处理。
对于复杂的 UI 交互,推荐使用 Single-page application(SPA)的方式。但是,对于简单的 UI,Express.js 模板可以跨越这条线。特别是,它不需要任何 JavaScript 代码。
布局 Layouts
布局被广泛使用,用于呈现整个页面。一般情况下,布局外面都有一层 HTML 容器。所有内容、导航、页脚和头信息都在其中。
使用布局的好处是它允许我们对每个页面的外观和感觉进行控制。就像我们之前介绍了一个 hbs.js 模块一样,现在我们将创建一个 layout.hbs 模板文件:
-- -------------------- ---- ------- --------- ----- ------ ------ ----- ---------------- ----- --------------- ---------------------------- ----------------- ------------------------ ----- ----------------------------- ----------------- ------- ------ --- -------- ----- ------------------------ ---------- ------- --- -------- ---- ------- --- ------- --------------------------------------------------------------------------- ------- ----------------------------------------------------------------------------- ------- -------
Partials 局部模板
局部模板是指一些定义好的、通常是包含在布局页的片段。例如,页眉、页脚和导航栏等可以使用局部模板优化。以下是一个 header.hbs 文件的示例:
-- -------------------- ---- ------- -------- ---- ------------- --------------- ------------------ ---- ------------------------ ---- ---------------------- ------- ------------- -------------------- ---------- ---------------------- --------------------------------- ----- ---------------------- ----------------- ----- ------------------------ ----- ------------------------ ----- ------------------------ --------- -- -------------------- ------------------ ------ ---- --------------- ---------------- ----------------------- --- ---------- ------------ --- ------------ ------------------------------------------------------- --- ------------ --------------------------------------------------------- --- ------------ ------------------------------------------------------------- ----- ------ ------ ------ ------------------ ---------
视图 Views
视图是指不包含其他内容的页面。它们只是简单地为我们呈现一些文本、图像和表单等内容。视图的另一个重要方面是:它们通过呈现零件来减少功能在其他地方的重复。
为了在 Express.js 中渲染视图文件,我们必须在 views 文件夹中创建子文件夹。为了避免出现不必要的错误,我们需要在 app.js 文件中设置 app.set('views', path.join(__dirname, 'views')),并将这个目录添加到 Express.js 的配置文件中。接下来,我们需要使用 res.locals 传递数据,以方便在布局和局部模板中引用。以下是要呈现的视图文件中的一些示例:
-- -------------------- ---- ------- ---- -------------- --- -------------- ------- -- - ---- --------- -------------- ---- --------------- --- -------------- ------- -- -- ----- --------- -------------- ---- ----------------- --- -------------- ----- ----------------- -------------- ---------- --------------- ------------- ------ ------------------------ ------ ----------- --------- ----------- ------------------ ---- ------ ---- ------ -------------------------- ------ ------------ ---------- ------------ ------------------ ---- ------- ---- ------ ------------------------------ --------- ------------ -------------- -------------------- ---- ------ ------------- ------------- ----------- ------- --------------
正如你所看到的,我们使用了木板的流控制结构,使用 {{#setLayout}}
和 {{/setLayout}}
包含内容。setLayout 是在 helpers.js 中定义的自定义辅助函数。
-- -------------------- ---- ------- -- --------- ------ - ------- - ---- --------- ----- ------- - - ------ ------- - ------ - - - -- --------------- ------- -------- ---- - -- -- --- --- ------ ---- --- ---- -- --- ---- -- -------- --- ------ ------ -- ---------------- ------------- --------- -- ---------------------------- - ---- ------ ---------------- -- ---------- ------- ---- ------- - ------ --- -------------------------- -- - ------ ------- -------
这个 helpers.ts 文件定义了三个助手函数:inc()、setLayout() 和 link()。其中,setLayout() 方法是我们独立评估的实现。它感知我们所在的环境,知道我们是在使用监听器服务器运行应用程序、编写数据表达式或打印错误消息,因此应该使用正确的参数。setLayout
发送<body>
信息,使用 twig.js
处理布局文件,然后调用回调函数呈现结果。正如你所看到的,它使用 render() 方法内置的布局名,并在局部模板中使用 {{> header}}````和
{{> footer}}``` 直接引用了其他文件。
抽象后的 MVC 实现
假设我们已经完全理解了如何分离视图、局部、布局和控制器。那么怎么样将其整合成简单的实现呢?以上代码展示了一个典型的完全抽象的 MVC 实现方式,设计到以下三个文件:
1. controller.ts
-- -------------------- ---- ------- ------ - -------- -------- - ---- --------- ------ --- ---- ------- ------ -------- --------- ----- -------- ---- --------- - ------------------ - ------ ----- ----- -- - ------ -------- ---------- ----- -------- ---- --------- - ------------------- - ------ ------ ----- -- - ------ -------- ------------ ----- -------- ---- --------- - --------------------- - ------ -------- ----- -- - ------ -------- ------------------- ----- -------- ---- --------- - --------------------- - ------ -------- ----- -- -
2. hbs.ts
-- -------------------- ---- ------- ------ ------ ---- -------------------- ------ ------- ---- ----------- ----- --- - --------------- -------------- --------- -------- ------- -------- -------- ----------- --------- - ----------------- ------------ --------- - ------------------ -- ------ ------- ---
3. app.ts
-- -------------------- ---- ------- ------ ------- ---- --------- ------ - -- ---------- ---- -------------- ------ --- ---- ------- -- ------ ------- ------ ----- --- - --------- -- ------- ------------- --------------- ---------------- -- ----- ---------------- --------- - --------- ------------- -------- ------ ----------------- ----------- -- ------ ------------ --------------------- ----------------- ---------------------- ------------------- ------------------------ -------------------- ------------------------------- -- ----- ------- ------ --------------------------- -- -- - ------------------- ------- -- ------------------------------------- --
现在,我们可以将 app.ts 文件作为应用程序的入口点,该文件需要创建 Express.js 服务器和事件循环代码,设置 Express.js 上的相关配置项,并运行一个 Express.js 应用程序。对象实例化、属性设置和路由设置都位于该文件中,但控制器和模板渲染代码都定义在独立的文件中。每个控制器只导出一个函数,根据处理器方法(GET、POST)来处理路由。最后,我们可以使用 hbs.ts 文件来设置 Handlebars 模板渲染器,并非常容易地注册自定义的 helpers 函数
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/197323