如何在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
相关产品推荐
相关产品推荐

