如何使用 Pug 创建更好的 Angular 模板
已发表: 2022-03-10作为一名开发人员,我很欣赏 Angular 应用程序的结构以及 Angular CLI 提供的许多配置选项。 组件为构建视图、促进代码可重用性、插值、数据绑定和其他视图业务逻辑提供了一种惊人的方法。
Angular CLI 支持多种内置 CSS 预处理器选项,用于组件样式,如 Sass/SCSS、LESS 和 Stylus。 但是,当涉及到模板时,只有两个选项可用:HTML 和 SVG。 尽管存在许多更有效的选择,例如 Pug、Slim、HAML 等。
在本文中,我将介绍您(作为 Angular 开发人员)如何使用 Pug 更有效地编写更好的模板。 您将学习如何在您的 Angular 应用程序中安装 Pug,以及如何将使用 HTML 的现有应用程序转换为使用 Pug。
管理图像断点
一个名为BreakPoint Observer的内置 Angular 功能为我们提供了一个强大的接口来处理响应式图像。 阅读更多关于允许我们在云中提供、转换和管理图像的服务。 阅读相关文章 →
Pug(以前称为 Jade)是一个模板引擎。 这意味着它是一种从集成了一些指定数据的模板生成文档的工具。 在这种情况下,Pug 用于编写模板,这些模板被编译为接收数据和呈现 HTML 文档的函数。
除了提供更简化的模板编写方式之外,它还提供了许多有价值的功能,这些功能不仅限于模板编写,例如促进代码可重用性、启用 JavaScript 代码嵌入、提供迭代器、条件等的混合。
尽管 HTML 被许多人普遍使用并且在模板中工作得很好,但它不是 DRY 并且很难阅读、编写和维护,尤其是对于较大的组件模板。 这就是 Pug 的用武之地。使用 Pug,您的模板变得更易于编写和阅读,并且您可以扩展模板的功能作为额外的好处。 在本文的其余部分,我将向您介绍如何在 Angular 组件模板中使用 Pug。
为什么你应该使用哈巴狗
HTML 基本上是重复的。 对于大多数元素,您必须有一个非 DRY 的开始和结束标签。 您不仅需要使用 HTML 编写更多内容,还需要阅读更多内容。 使用 Pug,没有开始和结束尖括号,也没有结束标记。 因此,您编写和阅读的代码要少得多。
例如,这是一个 HTML 表格:
<table> <thead> <tr> <th>Country</th> <th>Capital</th> <th>Population</th> <th>Currency</th> </tr> </thead> <tbody> <tr> <td>Canada</td> <td>Ottawa</td> <td>37.59 million</td> <td>Canadian Dollar</td> </tr> <tr> <td>South Africa</td> <td>Cape Town, Pretoria, Bloemfontein</td> <td>57.78 million</td> <td>South African Rand</td> </tr> <tr> <td>United Kingdom</td> <td>London</td> <td>66.65 million</td> <td>Pound Sterling</td> </tr> </tbody> </table>
这就是 Pug 中同一张表的样子:
table thead tr th Country th Capital(s) th Population th Currency tbody tr td Canada td Ottawa td 37.59 million td Canadian Dollar tr td South Africa td Cape Town, Pretoria, Bloemfontein td 57.78 million td South African Rand tr td United Kingdom td London td 66.65 million td Pound Sterling
对比两个版本的表格,Pug 看起来比 HTML 干净很多,代码可读性也更好。 尽管在这个小示例中可以忽略不计,但您在 Pug 表中编写的行数比在 HTML 表中少七行。 随着您随着时间的推移为项目创建更多模板,您最终会累积使用 Pug 编写更少的代码。
除了 Angular 模板语言提供的功能之外,Pug 还扩展了您可以在模板中实现的功能。 借助功能(例如 mixins、文本和属性插值、条件、迭代器等),您可以使用 Pug 更简单地解决问题,而不是编写整个单独的组件或导入依赖项并设置指令来满足需求。
哈巴狗的一些特点
Pug 提供了广泛的功能,但您可以使用哪些功能取决于您如何将 Pug 集成到您的项目中。 以下是一些您可能会觉得有用的功能。
- 使用
include
将外部 Pug 文件添加到模板中。
例如,假设您想要一个更简洁的模板,但不觉得需要创建额外的组件。 您可以从模板中取出部分并将它们放入部分模板中,然后将它们重新包含到原始模板中。
例如,在此主页组件中,“关于”和“服务”部分位于外部文件中,并包含在主页组件中。//- home.component.pug h1 Leone and Sons h2 Photography Studio include partials/about.partial.pug include partials/services.partial.pug
//- about.partial.pug h2 About our business p Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
//- services.partial.pug h2 Services we offer P Our services include: ul li Headshots li Corporate Event Photography
- 使用 mixins 重用代码块。
例如,假设您想重用代码块来创建一些按钮。 您将使用 mixin 重用该代码块。mixin menu-button(text, action) button.btn.btn-sm.m-1('(click)'=action)&attributes(attributes)= text +menu-button('Save', 'saveItem()')(class="btn-outline-success") +menu-button('Update', 'updateItem()')(class="btn-outline-primary") +menu-button('Delete', 'deleteItem()')(class="btn-outline-danger")
- 条件可以很容易地根据条件是否满足来显示代码块和注释。
- var day = (new Date()).getDay() if day == 0 p We're closed on Sundays else if day == 6 p We're open from 9AM to 1PM else p We're open from 9AM to 5PM
- 诸如
each
和while
之类的迭代器提供了迭代功能。ul each item in ['Eggs', 'Milk', 'Cheese'] li= item ul while n < 5 li= n++ + ' bottles of milk on the wall'
- 内联 JavaScript 可以用 Pug 模板编写,如上面的示例所示。
- 插值是可能的,并扩展到标签和属性。
- var name = 'Charles' p Hi! I'm #{name}. p I'm a #[strong web developer]. a(href='https://about.me/${name}') Get to Know Me
- 过滤器允许在 Pug 模板中使用其他语言。
例如,您可以在安装 JSTransformer Markdown 模块后在 Pug 模板中使用 Markdown。:markdown-it # Charles the Web Developer ![Image of Charles](https://charles.com/profile.png) ## About Charles has been a web developer for 20 years at **Charles and Co Consulting.**
这些只是 Pug 提供的一些功能。 您可以在 Pug 的文档中找到更广泛的功能列表。
如何在 Angular 应用程序中使用 Pug
对于使用 Angular CLI 6 及更高版本的新应用和现有应用,您需要安装ng-cli-pug-loader
。 它是 Pug 模板的 Angular CLI 加载器。
对于新组件和项目
- 安装
ng-cli-pug-loader
。ng add ng-cli-pug-loader
- 根据您的喜好生成组件。
例如,假设我们正在生成一个主页组件:ng gc home --style css -m app
- 将 HTML 文件扩展名
.html
更改为 Pug 扩展名.pug
。 由于最初生成的文件包含 HTML,您可以选择删除其内容并使用 Pug 重新开始。 但是,HTML 仍然可以在 Pug 模板中运行,因此您可以保持原样。 - 在组件装饰器中将模板的扩展名更改为
.pug
。@Component({ selector: 'app-component', templateUrl: './home.component.pug', styles: ['./home.component.css'] })
对于现有组件和项目
- 安装
ng-cli-pug-loader
。ng add ng-cli-pug-loader
- 安装 html2pug CLI 工具。 此工具将帮助您将 HTML 模板转换为 Pug。
npm install -g html2pug
- 要将 HTML 文件转换为 Pug,请运行:
html2pug -f -c < [HTML file path] > [Pug file path]
-f
以指示html2pug
它不应该将它生成的模板包装在html
和body
标记中。-c
标志让html2pug
知道在转换过程中元素的属性应该用逗号分隔。 我将在下面介绍为什么这很重要。 - 在组件装饰器中将模板的扩展名更改为
.pug
,如对于新组件和项目部分所述。 - 运行服务器以检查 Pug 模板的呈现方式是否没有问题。
如果有问题,请使用 HTML 模板作为参考,找出可能导致问题的原因。 这有时可能是缩进问题或未引用的属性,尽管很少见。 一旦您对 Pug 模板的呈现方式感到满意,请删除 HTML 文件。
从 HTML 迁移到 Pug 模板时要考虑的事项
您将无法将内联 Pug 模板与ng-cli-pug-loader
一起使用。 这只会渲染 Pug 文件,不会渲染组件装饰器中定义的内联模板。 所以所有现有的模板都需要是外部文件。 如果您有任何内联 HTML 模板,请为它们创建外部 HTML 文件并使用html2pug
将它们转换为 Pug。
转换后,您可能需要修复使用绑定和属性指令的模板。 ng-cli-pug-loader
要求 Angular 中的绑定属性名称用单引号或双引号括起来或用逗号分隔。 解决此问题的最简单方法是将-c
标志与html2pug
一起使用。 但是,这仅解决了具有多个属性的元素的问题。 对于具有单个属性的元素,只需使用引号。
如果您选择创建一个,这里描述的许多设置可以使用任务运行器或脚本或自定义 Angular 示意图进行自动化,以进行大规模转换。 如果您有几个模板并且想要进行增量转换,最好一次只转换一个文件。
Pug 模板中的 Angular 模板语言语法
在大多数情况下,Angular 模板语言语法在 Pug 模板中保持不变,但是,当涉及到绑定和一些指令(如上所述)时,您需要使用引号和逗号,因为()
、 []
和[()]
干扰 Pug 模板的编译。 这里有一些例子:
//- [src], an attribute binding and [style.border], a style binding are separated using a comma. Use this approach when you have multiple attributes for the element, where one or more is using binding. img([src]='itemImageUrl', [style.border]='imageBorder') //- (click), an event binding needs to be enclosed in either single or double quotes. Use this approach for elements with just one attribute. button('(click)'='onSave($event)') Save
像ngClass
、 ngStyle
和ngModel
这样的属性指令必须放在引号中。 *ngIf
、 *ngFor
、 *ngSwitchCase
和*ngSwitchDefault
等结构指令也需要放在引号中或与逗号一起使用。 模板引用变量(例如#var
)不会干扰 Pug 模板编译,因此不需要引号或逗号。 {{ }}
中的模板表达式不受影响。
在 Angular 模板中使用 Pug 的缺点和权衡
尽管 Pug 很方便并且改进了工作流程,但使用它也有一些缺点,并且在使用ng-cli-pug-loader
时需要考虑一些权衡。
文件不能使用include
包含在模板中,除非它们以.partial.pug
或.include.pug
结尾或称为mixins.pug
。 除此之外,模板继承不适用于ng-cli-pug-loader
,因此,尽管这是一个有用的 Pug 功能,但无法使用块、前置和附加 Pug 代码。
Pug 文件必须手动创建,因为 Angular CLI 只生成带有 HTML 模板的组件。 您将需要删除生成的 HTML 文件并创建一个 Pug 文件或仅更改 HTML 文件扩展名,然后更改组件装饰器中的templateUrl
。 尽管这可以使用脚本、原理图或任务运行程序自动完成,但您必须实施解决方案。
在较大的预先存在的 Angular 项目中,从 HTML 模板切换到 Pug 模板在某些情况下涉及大量工作和复杂性。 进行切换会导致大量破坏代码,需要逐个文件或使用自定义工具自动修复。 元素中的绑定和一些 Angular 指令需要用逗号引用或分隔。
不熟悉 Pug 的开发人员必须先学习语法,然后才能将其整合到项目中。 Pug 不仅仅是没有尖括号和结束标签的 HTML,它还涉及学习曲线。
当编写 Pug 并在 Angular 模板中使用它的功能时, ng-cli-pug-loader
不会让 Pug 模板访问组件的属性。 因此,这些属性不能用作变量、条件、迭代器和内联代码。 Angular 指令和模板表达式也无法访问 Pug 变量。 例如,使用 Pug 变量:
//- app.component.pug - var shoppingList = ['Eggs', 'Milk', 'Flour'] //- will work ul each item in shoppingList li= item //- will not work because shoppingList is a Pug variable ul li(*ngFor="let item of shoppingList") {{item}}
这是一个带有组件属性的示例:
//- src/app/app.component.ts export class AppComponent{ shoppingList = ['Eggs', 'Milk', 'Flour']; }
//- app.component.pug //- will not work because shoppingList is a component property and not a Pug variable ul each item in shoppingList li= item //- will work because shoppingList is a property of the component ul li(*ngFor="let item of shoppingList") {{item}}
最后, index.html
不能是 Pug 模板。 ng-cli-pug-loader
不支持这个。
结论
Pug 可能是在 Angular 应用程序中使用的一个了不起的资源,但它确实需要一些投资来学习和集成到一个新的或预先存在的项目中。 如果您准备好迎接挑战,您可以查看 Pug 的文档以了解有关其语法的更多信息并将其添加到您的项目中。 尽管ng-cli-pug-loader
是一个很棒的工具,但它在某些方面可能有所欠缺。 要定制 Pug 在您的项目中的工作方式,请考虑创建一个满足您项目要求的 Angular 示意图。