添加交互 (Action)
Action 是 Nex 的核心创新之一。它允许你直接在页面模块中定义处理异步请求(POST, PUT, DELETE)的函数,而无需离开当前文件的上下文。
1. Action 是什么?
在传统的 Web 开发中,处理按钮点击或表单提交通常需要定义路由、控制器和响应逻辑。在 Nex 中,这一切都被简化为 Action 函数。
- 局部性:交互逻辑与 UI 定义在同一个文件中。
- 声明式交互:Action 默认通过 HTMX 等声明式工具发送异步请求,无需编写 JavaScript。
-
无需 mount:Action 直接被调用,不需要重新执行页面的
mount或全屏渲染。
2. 单路径 Action (Referer-based)
这是最常用的 Action 模式。你只需在 HTML 中指定 hx-post="/函数名",Nex 会自动根据请求来源(Referer)找到对应的页面模块并执行该函数。
示例:计数器
创建 src/pages/counter.ex:
defmodule MyApp.Pages.Counter do
use Nex
def mount(_params) do
# 从状态中获取当前数值,默认为 0
%{count: Nex.Store.get(:count, 0)}
end
def render(assigns) do
~H"""
<div class="p-8 border rounded shadow">
<h2 class="text-xl">当前计数: <span id="count">{@count}</span></h2>
<!-- 点击按钮将发送 POST 请求到 /increment -->
<button hx-post="/increment"
hx-target="#count"
class="mt-4 px-4 py-2 bg-blue-500 text-white rounded">
增加 +1
</button>
</div>
"""
end
# 定义与 hx-post 路径同名的函数
def increment(_params) do
# 更新服务端状态
new_count = Nex.Store.update(:count, 0, &(&1 + 1))
# 直接返回一个字符串或 HEEx 片段,它将替换 hx-target 指定的内容
"#{new_count}"
end
end
3. 多路径 Action (Path-based)
如果你需要更符合 RESTful 风格的路径,或者需要在 URL 中传递 ID,可以使用多路径 Action。
示例:删除留言
路径:POST /messages/123/delete
Nex 会按以下规则解析:
-
找到
src/pages/messages/[id].ex(或src/pages/messages/index.ex)。 -
提取参数
id: "123"。 -
调用该模块中的
delete/1函数。
def delete(%{"id" => id}) do
# 执行删除逻辑
# ...
:empty # 返回 :empty 表示执行成功但不更新任何 DOM 元素
end
4. Action 的返回值类型
Action 可以返回多种类型的值,Nex 会根据返回值自动处理 HTTP 响应:
| 返回值类型 | 效果 | 状态码 |
|---|---|---|
| String / HEEx | 返回 HTML 片段,用于局部更新 | 200 OK |
:empty |
返回空内容,不更新任何 DOM | 200 OK |
{:redirect, url} |
让 HTMX 进行客户端跳转 | 200 OK + HX-Redirect |
{:refresh} |
让整个页面重新加载 | 200 OK + HX-Refresh |
Nex.stream(fn) |
开启 SSE 流式响应 | 200 OK + SSE |
练习:计数器进阶
在计数器页面添加一个“重置”按钮:
-
使用
hx-post="/reset"。 -
在模块中定义
reset/1函数。 -
函数逻辑:将
Nex.Store.put(:count, 0)。 -
返回值:使用
{:refresh}观察整个页面如何刷新。