name: liveview-patterns description: Phoenix LiveView 模式与最佳实践。在构建 LiveView 交互功能时加载。 user-invocable: false
LiveView 模式参考
用于构建 Phoenix LiveView 1.0/1.1 的参考。
铁律 — 切勿违反这些
- 在断开连接的 mount 中不要进行数据库查询 — 查询会运行两次(HTTP + WebSocket)。使用
assign_async - 始终对列表使用流 — 常规分配 = 每个用户 O(n) 内存。流 = O(1)
- 在订阅前检查 connected?/1 — 防止双重订阅
- 在 assign_async 闭包前提取变量 — 闭包会复制整个引用的变量
- 在 mount/3 中加载主要数据,分页在 handle_params/3 中 — handle_params 在每次 URL 更改时运行
- 切勿将 socket 传递给业务逻辑 — 在调用上下文前提取数据
- 在 UI 调试前检查变更集错误 — 静默表单保存 = 先检查
{:error, changeset},而不是视口/JS - 所有必需嵌入字段使用隐藏输入 — 嵌入模式中的每个必需字段,如果不可直接编辑,必须有一个
hidden_input - 切勿对生命周期值使用
assign_new—assign_new如果键存在则跳过函数。对语言环境、当前用户或每次 mount 刷新的任何值使用assign/3
内存影响
| 模式 | 3K 项 | 10K 用户 × 10K 项 |
|---|---|---|
| 常规分配 | ~5.1 MB | ~10+ GB |
| 流 | ~1.1 MB | 最小 (O(1)) |
决策:列表项 >100 → 使用流,而不是分配
快速模式
异步分配(关键)
def mount(%{"slug" => slug}, _session, socket) do
# 在闭包前提取所需值
scope = socket.assigns.current_scope
{:ok,
socket
|> assign_async(:org, fn -> {:ok, %{org: fetch_org(scope, slug)}} end)}
end
列表流
def mount(_params, _session, socket) do
{:ok, stream(socket, :items, Items.list_items())}
end
# 插入/更新/删除
stream_insert(socket, :items, item, at: 0)
stream_delete(socket, :items, item)
带 connected? 检查的 PubSub
def mount(_params, _session, socket) do
if connected?(socket), do: Chat.subscribe(room_id)
{:ok, socket}
end
导航决策树
相同 LiveView,不同参数? → patch / push_patch
不同 LiveView,相同 live_session? → navigate / push_navigate
不同 live_session 或非 LiveView? → href / redirect
组件决策树
组件是否需要内部状态和事件处理?
│
├── 是 → 是否封装应用程序逻辑(不仅仅是 DOM)?
│ ├── 是 → 使用 LiveComponent ✅
│ └── 否 → 重构为函数组件,由父组件处理
│
└── 否 → 使用函数组件 ✅
官方指南:“优先使用函数组件而非实时组件”
常见反模式
| 错误 | 正确 |
|---|---|
没有 assign_async 的数据库查询 |
对所有查询使用 assign_async |
对列表使用 assign(socket, items: list) |
使用 stream(socket, :items, list) |
没有 connected? 的 PubSub 订阅 |
if connected?(socket), do: subscribe() |
| 将 socket 传递给上下文函数 | 先提取 socket.assigns |
在 handle_event 中的业务逻辑 |
委托给上下文 |
在钩子中对语言环境/用户使用 assign_new |
使用 assign/3(必须每次 mount 运行) |
参考资料
详细模式,请参见:
references/async-streams.md- assign_async、stream_async、流references/forms-uploads.md- 表单、验证、文件上传references/components.md- 函数组件、LiveComponentsreferences/pubsub-navigation.md- PubSub、导航、JS 命令references/js-interop.md- 第三方 JS 库、phx-update=“ignore”、钩子references/channels-presence.md- Phoenix Channels、Presence、令牌认证