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

Phoenix LiveView如何让当前用户在整个视图栈中可用?

在Phoenix LiveView中实现类似Rails CurrentAttributes的功能

针对你从Rails转Phoenix后遇到的深层组件传递current_user的繁琐问题,有几种可行方案:

方案1:进程字典实现全局访问(快速便捷)

利用Erlang进程的隔离特性,在LiveView初始化时把当前用户存入进程字典,再封装一个全局调用函数:

# lib/your_app_web/live/current.ex
defmodule YourAppWeb.Current do
  @doc "获取当前登录用户"
  def user do
    Process.get(:current_user)
  end
end

# 在你的基础LiveView模块(比如YourAppWeb.LiveView)的mount回调中注入:
def mount(_params, _session, socket) do
  if current_user = socket.assigns[:current_user] do
    Process.put(:current_user, current_user)
  end
  {:ok, socket}
end

之后任意组件里直接调用YourAppWeb.Current.user()就能拿到当前用户,无需逐层传递assign。

注意:每个LiveView实例都是独立的Erlang进程,进程字典的数据不会跨实例污染,安全性有保障。但Elixir社区通常不推荐过度使用进程字典,因为它会让依赖关系变得隐晦,调试时可能增加复杂度。不过对于当前用户这类高频全局需求,这种方案的便捷性非常突出。

方案2:插槽上下文包裹(符合Phoenix显式风格)

如果你更倾向于遵循Elixir“显式优于隐式”的设计原则,可以通过自定义包裹组件自动传递上下文:

# lib/your_app_web/components/core_components.ex
defmodule YourAppWeb.CoreComponents do
  use Phoenix.Component

  def with_current_user(assigns) do
    ~H"""
    <%= render_slot(@inner_block, current_user: @current_user) %>
    """
  end
end

在顶层LiveView模板中用这个组件包裹所有需要访问用户的子组件:

<.with_current_user current_user={@current_user}>
  <.profile_card />
  <.deep_nested_comment_section />
</.with_current_user>

子组件可以直接从插槽参数中获取用户:

def profile_card(assigns) do
  ~H"""
  <div class="profile">
    <h2><%= @current_user.username %></h2>
  </div>
  """
end

这种方式既避免了逐层传递的麻烦,又保持了依赖关系的清晰,更贴合Phoenix的最佳实践。

补充说明

你现有的Plug逻辑已经把current_user存入conn的assigns,Phoenix LiveView会自动将conn的assigns同步到socket的assigns中,所以在mount回调里能直接拿到socket.assigns.current_user,无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 12:12:12