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

如何在Phoenix应用的多模板中全局访问变量

在Phoenix中实现全局数据加载(类似Express中间件)

针对你的需求,Phoenix里对应Express中间件的方案分两种场景:传统控制器渲染的页面,和LiveView页面,下面分别说明:

一、传统控制器页面(非LiveView)

Phoenix的Plug就是和Express中间件对应的机制,你可以写一个全局Plug来加载数据并注入到所有请求的assigns中:

  1. 新建一个Plug文件 lib/app_web/plugs/assign_global_data.ex:
defmodule AppWeb.Plugs.AssignGlobalData do
  import Plug.Conn

  def init(opts), do: opts

  def call(conn, _opts) do
    # 加载你需要的全局数据,比如新闻列表
    news = App.News.all()
    # 把数据存入conn的assigns,后续模板就能直接用@news
    assign(conn, :news, news)
  end
end
  1. 在路由的browser管道中添加这个Plug,确保所有浏览器请求都经过它:
    打开lib/app_web/router.ex,修改browser管道:
pipeline :browser do
  plug :accepts, ["html"]
  plug :fetch_session
  plug :fetch_live_flash
  plug :put_root_layout, html: {AppWeb.LayoutView, :root}
  plug :protect_from_forgery
  plug :put_secure_browser_headers
  # 新增这行,加入全局数据Plug
  plug AppWeb.Plugs.AssignGlobalData
end

这样根模板(比如lib/app_web/templates/layout/app.html.heex)里就能直接使用@news变量了。

二、LiveView页面

如果你的应用基于LiveView,或者需要在LiveView中全局加载数据,有两种实现方式:

方式1:根LiveView的mount方法

如果所有页面都基于同一个根LiveView,直接在它的mount回调里添加assign:

defmodule AppWeb.AppLive do
  use AppWeb, :live_view
  alias App.News

  @impl true
  def mount(_params, _session, socket) do
    # 加载全局数据
    news = News.all()
    # 把数据存入socket的assigns
    socket = assign(socket, :news, news)
    {:ok, socket}
  end
end

根LiveView的assign会自动传递给所有子LiveView,对应的根模板(比如lib/app_web/templates/layout/live.html.heex)也能直接用@news。

方式2:全局on_mount钩子(更灵活)

如果需要给所有LiveView统一注入数据,或者只想给部分LiveView添加,用on_mount钩子更合适:

  1. 在lib/app_web/live/live_helpers.ex中定义钩子:
defmodule AppWeb.LiveHelpers do
  import Phoenix.LiveView

  def on_mount(:assign_global_data, _params, _session, socket) do
    news = App.News.all()
    # :cont 表示继续执行LiveView的初始化流程
    {:cont, assign(socket, :news, news)}
  end
end
  1. 在lib/app_web.ex的live_view宏中注册这个钩子,让所有LiveView自动加载:
def live_view do
  quote do
    use Phoenix.LiveView,
      layout: {AppWeb.LayoutView, :live}

    unquote(view_helpers())
    # 新增这行,注册全局on_mount钩子
    on_mount AppWeb.LiveHelpers, :assign_global_data
  end
end

这样所有LiveView都会自动带上@news这个assign。

注意

如果你的应用同时存在传统控制器页面和LiveView页面,需要同时配置上述两种方案,确保根模板在两种场景下都能访问到@news。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 17:33:25