(这是一篇赞助文章)。
在浏览器所使用的语言中,我敢打赌,开发人员认为需要额外处理的第一种语言就是HTML。世界上的每一个CMS(除了故意不使用头部的CMS)本质上都是一个精心设计的HTML处理器:它们将内容和HTML模板挤压在一起。今天还有几十种专门的HTML处理语言存在。
HTML处理的主要需求是。
- 从部分内容组成完整的HTML文档
- 通过注入变量数据对HTML进行模板化处理
还有很多其他的功能,我们会讲到这些,但我认为这些是最重要的。
这项研究是在Frontend Masters(CSS-Tricks的官方学习合作伙伴)的支持下进行的。
需要前端开发培训吗?
Frontend Masters是获得培训的最佳场所。他们有关于所有最重要的前端技术的课程,从React到CSS,从Vue到D3,以及Node.js和Full Stack等。
考虑一下PHP。在这个网站上,我使用了PHP来拼凑一些模板化的HTML,以建立你现在看到的页面和完整的内容。
<h2>
<?php the_title(); // Templating! ?>
</h2>
<?php include("metadata.php"); // Partials! ?>
在上面的代码中,我把一些内容放到了一个HTML模板中,这个模板调用了另一个可能包含更多模板化HTML的PHP文件。PHP涵盖了HTML处理的两个大项,而且可以用成本低廉的主机来处理--我猜这是PHP驱动的网站在整个互联网中占很大比重的一个重要原因。
但是,PHP肯定不是唯一的HTML预处理器,而且它需要一个服务器来工作。还有许多其他的预处理器,有些是专门设计在网站被用户请求之前的构建过程中运行的。
让我们逐个语言来看看它是否支持某些功能以及如何支持。在可能的情况下,预处理器名称的链接会链接到相关文档。
它是否允许模板化?
你能在最终的HTML输出中混入数据吗?
| 处理器 | 例子 |
|---|---|
| 帕格 | ✅ |
- var title = "On Dogs: Man's Best Friend"; - var author = "enlore"; h1= title p Written with love by #{author} | |
| ERB | ✅ |
<%= title %> <%= description %> <%= @logged_in_user.name %> | |
| 马克笔 | ❌ |
| PHP | |
✅<?php echo $post.title; ?> <?php echo get_post_description($post.id) ?>也有HEREDOC | |
| 语法。 | |
| 瘦身 | ✅ |
tr td.name = item.name | |
| Haml | ✅ |
<h1><%= post.title %></h1> <div class="subhead"><%= post.subtitle %></div> | |
| 液体 | ✅ |
Hello {{ user.name }}! | |
| Go html/template | ✅ |
{{ .Title }} {{ $address }} | |
| 手柄 | ✅ |
{{firstname}} {{lastname}} | |
| 小胡子 | ✅ |
Hello {{ firstname }}! | |
| 小树枝 | ✅ |
{{ foo.bar }} | |
| 裤袜 | ✅ |
<h1>{{ title }}</h1> | |
| 装备 | ✅ |
<!-- $myVar = We finish each other's sandwiches. --> <p> <!-- $myVar --> </p> | |
| 谢尔盖 | ❌ |
它能做部分内容/包含内容吗?
你能从较小的部分组成HTML吗?
| 处理器 | 例子 |
|---|---|
| 帕格 | ✅ |
include includes/head.pug | |
| ERB | ✅ |
<%= render 'includes/head' %> | |
| 马克顿 | ❌ |
| PHP | ✅ |
<?php include 'head.php'; ?> <?php include_once 'meta.php'; ?> | |
| Slim | ⚠️ |
| 如果你能接触到Ruby的代码,看起来它可以做到 | |
| ,但你必须编写自定义的帮助器。 | |
| Haml | ✅ |
.content =render 'meeting_info' | |
| 液体 | ✅{% render head.html %} {% render meta.liquid %} |
| Go html/template | ✅{{ partial "includes/head.html" . }} |
| Handlebars | ⚠️ |
| 只通过提前注册一个部分 | |
| 。 | |
| 小胡子 | ✅{{> next_more}} |
| 小树枝 | ✅{{ include('page.html', sandboxed = true) }} |
| Nunjucks | ✅{% include "missing.html" ignore missing %} {% import "forms.html" as forms %} {{ forms.label('Username') }} |
| 套装 | ✅<!-- @import "someFile.kit" --> <!-- @import "file.html" --> |
| Sergey | ✅<sergey-import src="header" /> |
它能用include做局部变量吗?
比如说,你可以向include/partial传递数据,让它专门使用吗?例如,在Liquid中,你可以传递第二个变量参数给partial来使用。但在PHP或Twig中,没有这种能力--它们只能访问全局变量。
| 处理器 | 例子 | |
|---|---|---|
| PHP | ❌ | |
| ERB | ✅<%= render( partial: "card", locals: { title: "Title" } ) %> | |
| 符号化 | ❌ | |
| Pug | ⚠️ | |
| Pug有mixins | ||
| ,你可以放在一个单独的文件中调用。这个概念不太一样,但可以类似地使用。 | ||
| 瘦身 | ❌ | |
| Haml | ✅.content = render :partial => 'meeting_info', :locals => { :info => @info } | |
| 液体 | ✅{% render "name", my_variable**:** my_variable, my_other_variable**:** "oranges" %} | |
| Go html/template | ✅{{ partial "header/site-header.html" . }} (末尾的周期是"可变范围"。) | |
| 手把 | ✅{{> myPartial parameter=favoriteNumber }} | |
| 小胡子 | ❌ | |
| 小树枝 | ✅ | |
{% include 'template.html' with {'foo': 'bar'} only %} | ||
| 努尔加克 | ✅`{% macro field(name, value='', type='text') %} <input type="{{ type }}" name="{{ name }}" value="{{ value | escape }}" /> {% endmacro %}` |
| 套装 | ❌ | |
| 谢尔盖 | ❌ |
它能做循环吗?
有时你只需要100个<div>,你知道吗?或者更有可能的是,你需要在一个数据数组上循环,为每个条目输出HTML。有很多不同类型的循环,但至少有一个是不错的,而且你一般可以使它适用于任何你需要的循环。
| 处理器 | 例子 | ||
|---|---|---|---|
| PHP | ✅for ($i = 1; $i <= 10; $i++) { echo $i; } | ||
| ERB | ✅<% for i in 0..9 do %> <%= @users[i].name %> <% end %> | ||
| 马克笔 | ❌ | ||
| 帕格 | ✅for (var x = 1; x < 16; x++) div= x | ||
| 瘦身 | ✅- for i in (1..15) div #{i} | ||
| 哈姆雷特 | ✅`(1..16).each do | i | %div #{i}` |
| 橙色 | ✅{% for i in (1..5) %} {% endfor %} | ||
| 去html/template | ✅{{ range $i, $sequence := (seq 5) }} {{ $i }}: {{ $sequence } {{ end }} | ||
| 手柄 | ✅{{#each myArray}} <div class="row"></div> {{/each}} | ||
| 小胡子 | ✅{{#myArray}} {{name}} {{/myArray}} | ||
| 小树枝 | ✅{% for i in 0..10 %} {{ i }} {% endfor %} | ||
| 裤袜 | ✅{% set points = [0, 1, 2, 3, 4] %} {% for x in points %} Point: {{ x }} {% endfor %} | ||
| 装备 | ❌ | ||
| 谢尔盖 | ❌ |
它有逻辑吗?
Mustache在哲学上以 "无逻辑 "而闻名。 因此,有时,我们希望有一种模板语言,不混入任何其他功能,迫使你在另一层中处理你的业务逻辑。有时,模板中的小逻辑正是你所需要的。实际上,即使是Mustache也有一些基本的逻辑。
| 处理器 | 例子 |
|---|---|
| 帕格 | ✅#user if user.description h2.green Description else if authorised h2.blue Description |
| ERB | ✅<% if show %> <% endif %> |
| 马克笔 | ❌ |
| PHP | ✅<?php if (value > 10) { ?> <?php } ?> |
| 瘦身 | ✅- unless items.empty?如果你打开了逻辑少的模式。 |
- article h1 = title -! article p Sorry, article not found | |
| 哈姆雷特 | ✅if data == true %p true else %p false |
| 脚本 | ✅{% if user %} Hello {{ user.name }}! {% endif %} |
| Go html/template | ✅{{ if isset .Params "title" }} <h4>{{ index .Params "title" }}</h4> {{ end }} |
| 手拉手 | ✅{{#if author}} {{firstName}} {{lastName}} {{/if}} |
| 野蛮人 | ✅ |
| Mustache称自己为 "无逻辑的模板",这有点讽刺,但他们确实以"倒置部分 | |
| "的 | |
| 形式有逻辑。 |
{{#repo}} {{name}} {{/repo}} {{^repo}} No repos :( {{/repo}}
|
| Twig | ✅{% if online == false %} Our website is in maintenance mode. {% endif %} |
| Nunjucks | ✅{% if hungry %} I am hungry {% elif tired %} I am tired {% else %} I am good! {% endif %} |
| 套装 | ✅
它可以输出一个变量,如果它存在,它称之为 "选项"。
<dd class='<!-- $myVar? -->'> Page 1 </dd>
|
| 谢尔盖 | ❌ |
它有过滤器吗?
我这里所说的过滤器是指一种输出内容的方式,但在输出时要改变它。例如,转义特殊字符或大写文本。
| 处理器 | 例子 |
|---|---|
| 帕格 | ⚠️ |
| Pug认为过滤器 | |
| 是在Pug中使用其他语言的方法,而且没有任何开箱即用的过滤器。 | |
| ERB | ⚠️ |
| 无论Ruby有什么,比如。 |
"hello James!".upcase #=> "HELLO JAMES!"
|
| Markdown | ❌ |
| ǞǞǞ | ✅$str = "Mary Had A Little Lamb"; $str = strtoupper($str); echo $str; // Prints MARY HAD A LITTLE LAMB |
| Slim | ⚠️
只有私人的?
|
| Haml | ⚠️
非常具体的一个去除
空白的方法
。主要用于嵌入其他语言?
|
| 液体 | ✅
很多,你可以使用多种。
{{ "adam!" | capitalize | prepend: "Hello " }}
|
| Go html/template | ⚠️
有一堆函数
,其中很多是类似过滤器的。 |
| Handlebars | ⚠️
三括号做HTML转义,但除此之外,你必须注册你自己的块帮助器
。 |
| 小胡子 | ❌ |
| Twig | ✅{% autoescape "html" %} {{ var }} {{ var|raw }} {# var won't be escaped #} {{ var|escape }} {# var won't be doubled-escaped #} {% endautoescape %} |
| Nunjucks | ✅{% filter replace("force", "forth") %} may the force be with you {% endfilter %} |
| 套装 | ❌ |
| 谢尔盖 | ❌ |
它有数学吗?
有时,数学被直接植入了语言。有些语言是建立在其他语言之上的,因此使用其他语言来做数学运算。像Pug是用JavaScript写的,所以你可以在Pug中写JavaScript,它可以做数学。
| 处理器 | 支持 | |
|---|---|---|
| PHP | ✅<?php echo 1 + 1; ?> | |
| ERB | ✅<%= 1 + 1 %> | |
| 马克笔 | ❌ | |
| 帕格 | ✅- const x = 1 + 1 p= x | |
| 瘦身 | ✅- x = 1 + 1 p= x | |
| 哈姆雷特 | ✅%p= 1 + 1 | |
| 液体 | ✅`{{ 1 | plus: 1 }}` |
| Go html/template | ✅ | |
{{add 1 2}} | ||
| 手柄 | ❌ | |
| 小胡子 | ❌ | |
| 小树枝 | ✅{{ 1 + 1 }} | |
| Nunjucks | ✅{{ 1 + 1 }} | |
| 套装 | ❌ | |
| 谢尔盖 | ❌ |
它有槽/块吗?
槽的概念是一个模板,在它里面有特殊的区域,如果有内容,就会被填满。它在概念上类似于partials,但几乎相反。就像你可以把带参数的模板看作是模板调用这些参数来组成一个页面,而你几乎可以把槽看作是一点数据调用模板来把自己变成一个完整的页面。Vue以拥有槽而闻名,这个概念在Web组件中得到了体现。
| 处理器 | 例子 |
|---|---|
| PHP | ❌ |
| ERB | ❌ |
| 马克顿 | ❌ |
| 帕格 | ✅ |
| 你可以用 "混合元素 "来完成它 | |
| 瘦身 | ❌ |
| 哈姆雷特 | ❌ |
| 液体 | ❌ |
| Go html/template | ❌ |
| 手拉手 | ❌ |
| 小胡子 | ❌ |
| 小树枝 | ✅{% block footer %} © Copyright 2011 by you. {% endblock %} |
| 努尔加克 | ✅{% block item %} The name of the item is: {{ item.name }} {% endblock %} |
| 套装 | ❌ |
| 谢尔盖 | ✅<sergey-slot /> |
它有特殊的HTML语法吗?
HTML有 ,虽然空格有点重要(一个空格就是一个空格,但80个空格也是......一个空格),但它并不像Pug或Python那样真的是一种依赖空格的语言。将这些东西改变是一种语言的选择。如果这门语言所做的只是添加了额外的语法,但除此之外,你还是像正常的HTML一样写HTML,我认为这不是一种特殊的语法。如果这种语言改变了你写正常HTML的方式,那就是特殊语法。
| 处理器 | 例子 |
|---|---|
| PHP | ❌ |
| ERB | 在Ruby中,如果你想这样做,你一般会用Haml。 |
| 马克笔 | ✅这几乎是 |
| Markdown的全部意义。 |
# Title Paragraph with [link](#link). - List - List > Quote
|
| 帕格 | ✅ |
| Slim | ✅ |
| Haml | ✅ |
| 鱿鱼 | ❌ |
| Go html/template | ❌ |
| 手拉手 | ❌ |
| 小胡子 | ❌ |
| 小树枝 | ❌ |
| 努尔加克 | ❌ |
| 套装 | ⚠️
HTML注释指令。
|
| Sergey | ⚠️
一些发明的HTML标签。
|
等等等等--像React和Vue这样的东西呢?
我同意这些技术是基于组件的,用来做模板,并经常制作完整的页面。它们也可以实现这里列出的许多/大部分功能。它们,以及许多其他基于JavaScript的框架,通常也能够在服务器上或在构建步骤中运行,并产生HTML,即使有时感觉是事后的考虑(但并不总是)。它们还有其他一些可以非常引人注目的功能,比如范围/封装的样式,这需要HTML和CSS之间的合作,这是一个诱人的功能。
我没有把它们包括在内,因为它们一般都是有意用来在本质上制作DOM的。它们专注于数据检索和操作、状态管理、互动性等方面。它们并不真正专注于仅仅作为一个HTML处理器。如果你正在使用一个JavaScript框架,你可能不需要一个专门的HTML处理器,尽管它绝对可以做到。例如,将Markdown和JSX混合,或者将Vue模板和Pug混合。
我甚至没有把原生的网络组件放在这里,因为它们都是非常专注于JavaScript的。
其他考虑因素
- 速度 - 它的处理速度有多快?你关心吗?
- 语言- 它是用什么写的?它与你需要支持的机器兼容吗?
- 服务器或构建- 它是否需要运行网络服务器才能工作?还是可以在构建过程中运行一次?或者两者都可以?
超级图表
| 模板化 | 包括 | 本地变量 | 循环 | 逻辑 | 滤波器 | 数学 | 插槽 | 特殊语法 | |
|---|---|---|---|---|---|---|---|---|---|
| 术语 | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| ERB | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ⚠️ |
| 标记 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| 帕格 | ✅ | ✅ | ❌ | ✅ | ✅ | ⚠️ | ✅ | ✅ | ✅ |
| 瘦身 | ✅ | ⚠️ | ❌ | ✅ | ✅ | ⚠️ | ✅ | ❌ | ✅ |
| ✅ ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | ✅ | ❌ | ✅ |
| 鱿鱼 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| 浏览器/模板 | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | ✅ | ❌ | ❌ |
| 手把 | ✅ | ⚠️ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| 小胡子 | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| 树枝 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Nunjucks | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| 装备 | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ⚠️ |
| 谢尔盖 | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ⚠️ |
The postComparing HTML Preprocessor Featuresappeared first onCSS-Tricks.你可以通过成为MVP支持者来支持CSS-Tricks。