模板语法 #

一、HEEx概述 #

1.1 什么是HEEx #

HEEx (HTML+Embedded Elixir) 是Phoenix的模板引擎,结合了HTML和Elixir代码。它提供了编译时验证和优化的性能。

1.2 文件扩展名 #

text
.html.heex - HTML模板
.ex - 内联模板(~H宏)

1.3 基本结构 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

二、表达式 #

2.1 输出表达式 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

2.2 原始HTML #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

2.3 Elixir代码 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

三、条件语句 #

3.1 if/else #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

3.2 unless #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

3.3 cond #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

3.4 case #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

四、循环 #

4.1 for循环 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

4.2 带索引的循环 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

4.3 循环中的条件 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

4.4 空列表处理 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

五、属性绑定 #

5.1 静态属性 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

5.2 动态属性 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

5.3 布尔属性 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

5.4 多类名 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

5.5 属性展开 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

六、插槽 #

6.1 基本插槽 #

elixir
attr :title, :string, required: true
slot :inner_block, required: true

def card(assigns) do
  ~H"""
  <div class="card">
    <h2><%= @title %></h2>
    <div class="card-body">
      <%= render_slot(@inner_block) %>
    </div>
  </div>
  """
end

使用:

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

6.2 命名插槽 #

elixir
slot :header
slot :footer

def layout(assigns) do
  ~H"""
  <div class="layout">
    <header>
      <%= render_slot(@header) || "Default Header" %>
    </header>
    <main>
      <%= render_slot(@inner_block) %>
    </main>
    <footer>
      <%= render_slot(@footer) || "Default Footer" %>
    </footer>
  </div>
  """
end

使用:

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

6.3 插槽参数 #

elixir
attr :items, :list, required: true
slot :item, required: true

def list(assigns) do
  ~H"""
  <ul>
    <%= for item <- @items do %>
      <li><%= render_slot(@item, item) %></li>
    <% end %>
  </ul>
  """
end

使用:

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

七、特殊语法 #

7.1 特殊属性 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

7.2 动态标签 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

7.3 注释 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

八、内联模板 #

8.1 ~H宏 #

elixir
defmodule HelloWeb.PageHTML do
  use HelloWeb, :html

  def home(assigns) do
    ~H"""
    <div class="container">
      <h1><%= @title %></h1>
      <p><%= @description %></p>
    </div>
    """
  end
end

8.2 函数组件 #

elixir
defmodule HelloWeb.Components do
  use Phoenix.Component

  attr :name, :string, required: true
  attr :age, :integer, default: 0

  def user_card(assigns) do
    ~H"""
    <div class="user-card">
      <h3><%= @name %></h3>
      <p>Age: <%= @age %></p>
    </div>
    """
  end
end

九、属性定义 #

9.1 attr宏 #

elixir
use Phoenix.Component

attr :title, :string, required: true
attr :class, :string, default: ""
attr :disabled, :boolean, default: false
attr :type, :atom, values: [:primary, :secondary, :danger], default: :primary
attr :data, :map, default: %{}

def button(assigns) do
  ~H"""
  <button class={["btn", "btn-#{@type}", @class]} disabled={@disabled}>
    <%= render_slot(@inner_block) %>
  </button>
  """
end

9.2 属性类型 #

类型 说明
:string 字符串
:integer 整数
:float 浮点数
:boolean 布尔值
:atom 原子
:list 列表
:map 映射
:any 任意类型

9.3 属性选项 #

选项 说明
required: true 必需属性
default: value 默认值
values: […] 允许的值

十、表单 #

10.1 表单组件 #

elixir
attr :for, :any, required: true
attr :action, :string, default: "#"
attr :method, :string, default: "post"

def form(assigns) do
  ~H"""
  <form action={@action} method={@method}>
    <input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
    <%= render_slot(@inner_block) %>
  </form>
  """
end

10.2 输入组件 #

elixir
attr :name, :string, required: true
attr :type, :string, default: "text"
attr :value, :string, default: ""
attr :placeholder, :string, default: ""
attr :required, :boolean, default: false

def input(assigns) do
  ~H"""
  <input
    type={@type}
    name={@name}
    value={@value}
    placeholder={@placeholder}
    required={@required}
  />
  """
end

10.3 使用表单 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

十一、链接 #

11.1 link组件 #

elixir
attr :to, :any, required: true
attr :method, :atom, values: [:get, :post, :put, :patch, :delete], default: :get
attr :class, :string, default: ""

def link(assigns) do
  ~H"""
  <a href={@to} class={@class} data-method={@method}>
    <%= render_slot(@inner_block) %>
  </a>
  """
end

11.2 使用链接 #

heex
defmodule HelloWeb.Layouts do
  use HelloWeb, :html

  embed_templates "layouts/*"
end

十二、总结 #

12.1 核心语法 #

语法 说明
<%= %> 输出表达式
<% %> 执行代码
:let 解构参数
:for 循环
:if 条件
:else 否则
:show 显示条件

12.2 属性绑定 #

语法 说明
attr= 动态属性
class= 类名列表
disabled= 布尔属性
展开属性

12.3 下一步 #

现在你已经了解了模板语法,接下来让我们学习 布局与组件,深入了解页面组织!

最后更新:2026-03-28