如何通过EJS模板将数据传入Google Charts的drawGraphs()函数
如何通过EJS模板将数据传入Google Charts的drawGraphs()函数
嘿,我看你遇到的问题是EJS模板里的前端JavaScript拿不到后端传的graphs变量对吧?其实原因很简单:后端传给EJS的graphs是模板渲染变量,它只在EJS的模板标签(比如<% %>、<%= %>)里有效,直接在前端<script>里写graphs的话,浏览器根本不知道这个变量是什么——因为它不在全局作用域里。
下面给你一步步解决的方法:
第一步:把后端数据转成前端可访问的JS变量
在你的chart.ejs的<script>标签最开头,先添加一行代码,用EJS把后端的graphs对象转换成JSON字符串,再赋值给一个前端全局变量:
// 把后端传的graphs变量转成前端能直接用的JS对象 const graphsData = <%= JSON.stringify(graphs) %>;
这里JSON.stringify(graphs)会把后端的JavaScript对象转成合法的JSON字符串,EJS的<%= %>会直接把这个字符串输出到页面里,所以前端JS会把它当成一个原生的JavaScript对象来解析,这样你就能在前端代码里用graphsData访问到后端的数据了。
第二步:修正前端的图表绘制逻辑
看你后端传的myGraph是单个对象(不是数组),但你原来的drawGraphs()里写了graphs.forEach(g => {})——单个对象是没有forEach方法的,这也是潜在的问题。所以我们要调整drawGraphs()的逻辑,直接处理单个图表:
修改后的drawGraphs()函数应该是这样:
function drawGraphs() { console.log("Entered drawGraphs()") console.log(graphsData) // 现在用我们定义的前端变量 // 先添加承载图表的div appendDivToBody(graphsData.name, 'width: 1200px; height: 500px'); // 直接调用drawGraph绘制这个图表 drawGraph(graphsData.name, graphsData.myData); }
第三步:完整的修改后chart.ejs代码
把这些修改整合到你的chart.ejs里,完整的<script>部分应该是这样:
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> <script type="text/javascript"> // 新增:把后端数据转成前端变量 const graphsData = <%= JSON.stringify(graphs) %>; google.charts.load('current', { 'packages': ['corechart'] }); google.charts.setOnLoadCallback(drawGraphs); function drawGraphs() { console.log("Entered drawGraphs()") console.log(graphsData) appendDivToBody(graphsData.name, 'width: 1200px; height: 500px'); // 因为是单个图表,不用forEach,直接调用drawGraph drawGraph(graphsData.name, graphsData.myData); } function drawGraph(graphName, graphData) { var data = new google.visualization.DataTable(); data.addColumn('string', 'Toppings'); data.addColumn('number', 'Slices'); data.addRows(graphData); var options = { title: `${graphName}`, 'width': 500, 'height': 300 }; var chart = new google.visualization.PieChart(document.getElementById(graphName)); chart.draw(data, options); } function appendDivToBody(id, style) { var div = document.createElement('div'); div.id = id; div.style = style; document.getElementsByTagName('body')[0].appendChild(div); } </script>
为什么这样能行?
JSON.stringify(graphs)保证了后端的JavaScript对象能安全地转换成字符串,然后被前端JS解析成原生对象,不会有语法错误。- 把数据赋值给前端的
graphsData变量后,drawGraphs()就能在浏览器的全局作用域里访问到它了,不会再出现ReferenceError: graphs is not defined的错误。 - 修正了
forEach的问题,因为你现在传的是单个图表对象,不是数组,直接调用绘制函数就可以了。如果以后你需要传多个图表,只需要把后端的myGraph改成数组(比如let myGraphs = [graph1, graph2]),然后前端用graphsData.forEach(g => {})就可以了。
现在重启你的服务器,访问localhost:3000,应该就能看到饼图正常显示了!
备注:内容来源于stack exchange,提问作者Adrian Hood Sr
相关产品推荐
相关产品推荐

