ERB 和 Haml 哪个好?Rails 视图模板引擎对比
ERB 直白冗长但人人会写,Haml 简洁优雅但要适应缩进语法。本文从可读性、动态属性、局部模板、转义、性能与工具链全面对比两大 Rails 模板引擎,帮你做出选择。
团队协作、新人友好、与 HTML 原型互转方便选 ERB(Rails 默认,生态最稳);追求视图简洁、能接受缩进语法且团队意见统一时选 Haml。两者性能差距在现代硬件上不构成决策因素,可维护性才是。
语法风格:标签 vs 缩进
同一段列表渲染,ERB 写法:
<ul class="users">
<% @users.each do |user| %>
<li class="<%= user.active? ? 'active' : '' %>">
<%= link_to user.name, user_path(user) %>
</li>
<% end %>
</ul>
Haml 写法:
%ul.users
- @users.each do |user|
%li{ class: ('active' if user.active?) }
= link_to user.name, user_path(user)
Haml 消灭了近一半的字符:没有闭合标签(靠缩进推断结构)、%div.class 简写、- 执行代码、= 输出。代价是团队所有人都要适应"缩进即语法",且与设计师给的 HTML 原型不能直接互贴。
可读性的真相
Haml 支持者认为结构即缩进,嵌套错误一目了然;ERB 支持者认为尖括号才是 HTML 的本色,grep 和编辑器支持更成熟。实践中 readability 的分水岭在局部模板的拆分粒度——两种引擎下,拆得好的视图都好读,嵌套十层的视图都难救。
动态属性与条件类名
ERB 在属性里嵌 Ruby 需要字符串插值,条件复杂时行内可读性下降;Haml 的属性用 Ruby Hash 语法,天然支持条件与数组:
%input{ type: 'text', disabled: @form.locked?, data: { controller: 'mask' } }
对 Tailwind/Stimulus 风格(大量 data 属性与条件类名)的项目,Haml 的 Hash 属性语法明显更顺手。
局部模板与布局
两者的 partial 机制一致(_user.html.erb / _user.html.haml,render 'user'),布局 yield 也相同。混用是允许的:布局用 ERB、局部模板用 Haml 都没问题,Rails 按扩展名分别处理。
空白控制与转义
- 空白:Haml 用
~(保留空白)和><(去除内外空白)精细控制;ERB 用<%- -%>修剪换行,写内联元素(如链接后跟标点)时 Haml 的控制更直观。 - 转义:两者都默认 HTML 转义输出。ERB 用
raw/html_safe放行,Haml 用!=。规则相同:永远不要把用户输入原样输出。
注释、多行表达式与过滤器
Haml 的 / 是 HTML 注释、-# 是引擎级注释(不出现在最终 HTML,适合写敏感备注);ERB 只有 <%# %> 一种。多行 Ruby 表达式在 ERB 里可以自然换行,Haml 需要用 | 续行,长链式调用时略丑。Haml 的过滤器(:javascript、:css、:markdown)可以在模板内直接嵌其他语言,这是独有便利。
性能与工具链
渲染性能上两者都在编译为 Ruby 后执行,Haml 历史上略慢但近版本差距已缩到可忽略;真正的瓶颈永远在 partial 数量和数据库查询。工具链方面:ERB 的编辑器高亮、Lint(erb-lint)、IDE 跳转支持最完整;Haml 有 haml-lint,主流编辑器插件齐全但生态密度不及 ERB。
常见问题(FAQ)
Q:新项目模板引擎怎么选?
默认 ERB。除非团队全员 Haml 拥趸,否则默认选项带来的招聘成本、示例代码兼容性(Rails 文档和 gem README 都是 ERB)优势是实打实的。
Q:已有 ERB 项目能迁到 Haml 吗?
可以用 html2haml 工具批量转换,但收益有限、回归风险不小。更务实的做法是保持 ERB,通过更细的 partial 拆分和 helper 提炼改善可读性。
Q:Haml 里写复杂 Ruby 逻辑合适吗?
不合适——但这与引擎无关。视图里超过两行的逻辑都应该下沉到 helper、decorator 或 ViewComponent;Haml 的简洁语法反而更容易暴露"逻辑写错层"的问题。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。