如何在Rails 7中传递SVG/Div ID给JS函数以展示多D3图表
Rails 7 中传递动态 SVG ID 给 D3 图表函数的解决方案
1. 修正视图代码,动态传递 SVG ID
首先把视图里硬编码的 ID 改成动态生成的,确保每个 SVG 元素的 ID 能正确传给 D3 函数:
<%= content_tag "svg", class: 'chart', id: "#{chart_type}_#{chart_num}", data: {chart_type: chart_type, chart_num: chart_num} do %> <script> line('#<%= "#{chart_type}_#{chart_num}" %>'); </script> <% end %>
这里通过 Rails 字符串插值生成唯一的 SVG ID,并直接传递给 line 函数,避免硬编码固定值。
2. 修正 JavaScript 函数,正确使用参数
原代码存在两个问题:硬编码选择器、错误地将 ID 作为元素名 append,修正后的代码如下:
import * as d3 from "d3"; // 将函数挂载到全局 window 对象,确保内联脚本能访问到 window.line = function(chart_id) { // 使用传入的 chart_id 参数选择目标 SVG const svg = d3.select(chart_id) .attr('width', 400) .attr('height', 400) .style('background-color', 'black'); // 要 append 的是 'line' 元素,而非 chart_id svg.append('line') .style("stroke", "lightgreen") .style("stroke-width", 10) .attr("x1", 0) .attr("y1", 0) .attr("x2", 200) .attr("y2", 200); }
说明:由于 Rails 通过 importmap 导入的模块默认处于模块作用域,内联脚本无法直接访问,因此需要将 line 函数挂载到 window 全局对象。
3. 可选:无内联脚本的优雅实现(推荐)
如果不想使用内联脚本,可以通过监听 DOM 加载事件,利用 data 属性自动初始化图表:
视图代码
<%= content_tag "svg", class: 'chart', id: "#{chart_type}_#{chart_num}", data: {chart_type: chart_type, chart_num: chart_num, chart_renderer: 'line'} do %> <% end %>
JavaScript 代码(修改 line.js)
import * as d3 from "d3"; // 封装独立的渲染函数 function renderLineChart(chartId) { const svg = d3.select(chartId) .attr('width', 400) .attr('height', 400) .style('background-color', 'black'); svg.append('line') .style("stroke", "lightgreen") .style("stroke-width", 10) .attr("x1", 0) .attr("y1", 0) .attr("x2", 200) .attr("y2", 200); } // 页面加载完成后自动初始化所有图表 document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('.chart').forEach(svgEl => { const chartId = `#${svgEl.id}`; const renderer = svgEl.dataset.chartRenderer; if (renderer === 'line') { renderLineChart(chartId); } // 可扩展支持其他图表类型,如 bar、pie 等 }); });
这种方式完全移除内联脚本,通过 data 属性标记图表类型,自动匹配对应的渲染函数,更符合现代前端开发规范。
内容的提问来源于stack exchange,提问作者Anne Lalsingh
相关产品推荐
相关产品推荐

