You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Phoenix Live View中phx-update="append"导致DOM容器为空的问题

Phoenix LiveView temporary_assigns配合phx-update="append"时DOM为空问题

问题重现

配置temporary_assigns并使用phx-update="append"后,容器始终为空,初始子元素从未显示;改用phx-update="stream"则正常工作。

后端mount代码

{:ok,
 assign(socket,
   chats: [%{id: 1, message: "hey"}],
   temporary_assigns: [chats: []]
 )}

前端模板代码

<main
  id="chat-messages"
  phx-update="append"
  class="bg-blue-100 w-full h-[640px] p-3 flex flex-col gap-2"
>
  <section :for={chat <- @chats}>
    <div
      id={"chat-#{chat.id}"}
      class="w-full max-w-xs p-4 text-gray-500 bg-white rounded-lg shadow dark:bg-gray-800 dark:text-gray-400"
    >
      <div class=" text-sm font-normal">
        <div class="text-sm font-normal">
          <%= chat.message %>
          <%= chat.id %>
        </div>
      </div>
    </div>
  </section>
</main>

问题原因

temporary_assigns的核心特性是每次渲染完成后,将指定assign重置为设定的初始值。这里mount时设置的chats初始数据,在首次渲染完成后被立刻重置为[];而phx-update="append"的规则是:当assign更新时追加新元素,但如果assign从有值变为空,LiveView会同步DOM,移除容器内所有对应元素,最终导致初始渲染的子元素被清空。

而phx-update="stream"是官方专门配合temporary_assigns设计的机制,它通过条目ID跟踪已渲染元素,不会因assign被清空而移除已有元素,只会处理新增条目,因此可以正常显示内容。

解决方案

方案1:保留phx-update="append" + temporary_assigns

调整初始数据的加载时机,避免mount时直接设置初始chats导致渲染后被清空:

  1. 修改mount代码,仅初始化temporary_assigns并发送异步加载消息:
def mount(_params, _session, socket) do
  send(self(), :load_initial_chats)
  {:ok, assign(socket, temporary_assigns: [chats: []])}
end
  1. 添加handle_info处理初始数据加载:
def handle_info(:load_initial_chats, socket) do
  {:noreply, assign(socket, chats: [%{id: 1, message: "hey"}])}
end

初始数据通过异步消息触发渲染,完成后chats被重置为空,但此时容器内的元素已被追加,且无后续assign更新触发DOM同步,因此元素会被保留。

方案2:改用stream机制(推荐)

既然phx-update="stream"可以正常工作,这是Phoenix官方推荐的配合temporary_assigns的方案,长期维护更友好。只需将模板中的phx-update="append"改为phx-update="stream",并确保子元素ID唯一即可(你已完成该配置)。


内容的提问来源于stack exchange,提问作者user15254140

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 02:20:39