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

如何在Elixir Phoenix中从数据库向JavaScript Hook传递数据

不用额外建API,用Phoenix LiveView自带的机制就能搞定,给你两种最简便的方案:

方案1:通过DOM data属性传递初始数据

适合页面加载时直接渲染图表的场景,把Ecto查询到的数据转成JSON,绑定到Hook元素的data属性里。

步骤1:后端LiveView查询数据

假设你已经有对应的Ecto Schema(比如TreeMapData),字段包含数组类型的labels和parents,在LiveView的mount方法里从数据库取数据:

defmodule MyAppWeb.PlotLive do
  use MyAppWeb, :live_view
  alias MyApp.TreeMapData

  @impl true
  def mount(_params, _session, socket) do
    # 按业务逻辑查询数据,这里示例取第一条
    %{labels: labels, parents: parents} = TreeMapData |> Repo.one()
    {:ok, assign(socket, labels: labels, parents: parents)}
  end
end

步骤2:模板绑定Hook和数据

在LiveView的HEEX模板里,给Hook元素加上data属性:

<div phx-hook="myPlot" 
     data-labels={Jason.encode!(@labels)} 
     data-parents={Jason.encode!(@parents)}>
  <!-- Plotly图表会渲染在这里 -->
</div>

步骤3:修改JS Hook读取数据渲染

调整你的Hook代码,从元素的dataset里解析数据后传给Plotly:

let liveSocket = new LiveSocket("/live", Socket, {
  params: {_csrf_token: csrfToken},
  hooks:{
    myPlot:{
      mounted(){
        // 读取并解析data属性里的JSON数据
        const labels = JSON.parse(this.el.dataset.labels);
        const parents = JSON.parse(this.el.dataset.parents);
        
        // 直接用当前元素作为图表容器,不用额外创建div
        Plotly.newPlot(this.el, [{
          type: "treemap",
          labels: labels,
          parents: parents
        }])
      }
    }
  }
})

方案2:通过LiveView事件推送动态数据

如果需要后续动态更新图表(比如用户点击刷新),用push_event的方式更灵活,也能覆盖初始加载场景。

步骤1:后端查询并推送事件

在LiveView里查询数据后,推送给客户端:

defmodule MyAppWeb.PlotLive do
  use MyAppWeb, :live_view
  alias MyApp.TreeMapData

  @impl true
  def mount(_params, _session, socket) do
    data = TreeMapData |> Repo.one()
    socket = socket
             |> assign(data)
             |> push_event("plot_data", data)
    {:ok, socket}
  end

  # 处理用户触发的刷新事件
  @impl true
  def handle_event("refresh_plot", _params, socket) do
    data = TreeMapData |> Repo.one()
    socket = socket
             |> assign(data)
             |> push_event("plot_data", data)
    {:noreply, socket}
  end
end

步骤2:修改JS Hook监听事件

Hook里监听后端推送的事件,收到数据后渲染/更新图表:

let liveSocket = new LiveSocket("/live", Socket, {
  params: {_csrf_token: csrfToken},
  hooks:{
    myPlot:{
      mounted(){
        // 监听后端推送的"plot_data"事件
        this.handleEvent("plot_data", (data) => {
          Plotly.newPlot(this.el, [{
            type: "treemap",
            labels: data.labels,
            parents: data.parents
          }])
        });
      }
    }
  }
})

可选:模板加刷新按钮

如果需要手动刷新,在模板里加触发按钮:

<div phx-hook="myPlot">
  <!-- Plotly图表容器 -->
</div>
<button phx-click="refresh_plot">刷新图表</button>

两种方案对比

  • data属性方案:实现简单,适合静态初始数据,无需额外事件监听。
  • push_event方案:支持动态更新,适合需要交互刷新的场景,也能覆盖初始加载。

这两种方法都不用额外创建API路由,完全利用Phoenix LiveView的现有机制,是最简便的实现方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 08:43:14