EJS & Plotly: 解决OHLC图表渲染及数据传递问题
2025-01-15 20:30:54
解决EJS中Plotly OHLC图表渲染及数据传递问题
在Web开发中,动态生成图表是常见需求。使用 Plotly.js 这类强大的JavaScript图表库配合EJS这类模板引擎可以创建丰富的数据可视化效果。然而,在将数据从后端传递到前端的过程中,特别是在EJS模板中渲染 Plotly 图表时,可能会遇到一些阻碍,例如数据无法正确传递、图表不显示等等。 这个问题通常与EJS模板的数据传递和Plotly的初始化方式有关。下面针对此问题分析可能原因并提供有效的解决方案。
问题分析
上述代码的核心问题在于尝试直接在 chart.ejs
中使用EJS语法渲染一个 JavaScript对象 (变量 result
) 并将其作为 Plotly 图表的数据源,或者引入一个含有 result
变量的chart.js
脚本文件。 这会导致一系列的问题:
- EJS模板解析时机: EJS 是在服务端解析的, 而Plotly 图表绘制需要使用 JavaScript在浏览器中执行。服务端处理
chart.ejs
时会解析所有EJS标签, 渲染完成后将结果发到浏览器, 浏览器此时收到的并不是 JavaScript 对象本身,而是包含对象内容的字符串,Plotly不能直接识别它,导致数据无法正确传入。 - JavaScript 执行环境: 尝试直接在
chart.ejs
中的<script>
标签中使用result
变量,同样会失败,原因是:<script>
中的result
变量必须是一个浏览器中的 JavaScript 可用的对象,而不是服务端的ejs
渲染数据。
解决方案
为了解决上述问题,核心思想是将 Plotly 绘图所需要的数据转化为前端可直接使用的 JavaScript 对象,在前端进行初始化绘图操作。
方案一:将数据以 JSON 形式内联到 HTML
这是最为常见和简便的做法: 在服务端,把要传递的数据对象result
通过 EJS ${JSON.stringify(result)}
转换成JSON字符串, 将其插入 HTML 的 <script>
标签中。这样一来, 浏览器端的 JavaScript 代码可以直接读取并解析该JSON字符串,获得 Plotly 可用的 JavaScript 数据对象。
操作步骤:
- 修改
chart.ejs
: 将传递过来的result
对象序列化为 JSON 字符串, 赋值给window.resultData
, 通过这个变量名将数据传递给 Plotly 的逻辑处理部分:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<link rel="stylesheet" href="styles/main.css">
<script src='https://cdn.plot.ly/plotly-2.35.2.min.js'></script>
</head>
<body>
<h1>OHLC Chart</h1>
<div id="ohlc-result-div"></div>
<script>
// Pass result from EJS template as a JavaScript object to the front end
window.resultData = <%- JSON.stringify(result) %>;
const trace = {
x: window.resultData.x,
open: window.resultData.open,
high: window.resultData.high,
low: window.resultData.low,
close: window.resultData.close,
type: "ohlc",
increasing: { line: { color: "#17BECF" } },
decreasing: { line: { color: "#7F7F7F" } },
};
const layout = {
title: "OHLC Chart",
dragmode: "zoom",
xaxis: {
title: "Date",
type: "date",
},
yaxis: {
title: "Price",
type: "linear",
},
};
Plotly.newPlot("ohlc-result-div", [trace], layout);
</script>
</body>
</html>
- 代码分析: 使用
<%- %>
可以插入非转义 HTML 代码, 同时JSON.stringify()
函数 将result
转换成了字符串。 然后通过window.resultData
来创建一个全局变量来存放这个字符串数据。在之后的script
代码块中就可以用这个全局变量来拿到绘图需要的数据, 创建trace
和layout
。 之后使用Plotly.newPlot
就可以绘制图像。
说明:
- 此方法直接将数据嵌入到页面 HTML 中, 简洁高效。对于较小的数据集非常合适。
- 此方法避免了不必要的网络请求。
- 将数据传递到
window
的同时也可以将它赋给某个自定义变量,根据开发需要进行调整。
方案二:使用 <script>
引入外部 JavaScript 文件进行绘制
如果想分离 chart.ejs
中的HTML和JavaScript, 或者 JavaScript 代码逻辑复杂, 可以使用外部JavaScript文件进行绘制,并在服务器端使用类似 JSON.stringify(result)
的方式将数据传递到前端。 区别在于我们创建一个专门的 js 文件来处理数据并且用 JavaScript 全局变量来传递。
操作步骤:
- 修改
chart.ejs
: 在chart.ejs
中增加一段脚本,用来传递result
对象并声明chart.js
文件,确保它在plotly.js
之后执行。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> <link rel="stylesheet" href="styles/main.css"> <script src='https://cdn.plot.ly/plotly-2.35.2.min.js'></script> </head> <body> <h1>OHLC Chart</h1> <div id="ohlc-result-div"></div> <script> // Pass result from EJS template as a JavaScript object to the front end window.resultData = <%- JSON.stringify(result) %>; </script> <script src="/chart.js" defer></script> </body> </html>
- 修改
chart.js
:将之前直接使用的result
改为window.resultData
。const trace = { x: window.resultData.x, open: window.resultData.open, high: window.resultData.high, low: window.resultData.low, close: window.resultData.close, type: "ohlc", increasing: { line: { color: "#17BECF" } }, decreasing: { line: { color: "#7F7F7F" } }, }; const layout = { title: "OHLC Chart", dragmode: "zoom", xaxis: { title: "Date", type: "date", }, yaxis: { title: "Price", type: "linear", }, }; Plotly.newPlot("ohlc-result-div", [trace], layout);
-
代码分析: 此方法需要增加
script
标签。首先, 用window.resultData
将 EJS 传递的数据保存,保证chart.js
可以获取到它。 注意保证引入的顺序, 需要在Plotly
引入之后,chart.js
脚本文件在包含数据的script
代码之后, 确保数据加载到全局作用域再使用。
说明: -
将 Plotly 的逻辑独立到
chart.js
,使代码结构更加清晰和模块化,易于维护。 -
需要注意
script
标签的加载顺序。
安全提示
无论采用哪种方案,都应该注意以下安全事项:
- 避免直接在模板中拼接 JavaScript 代码,以防止潜在的跨站点脚本(XSS)攻击。
- 在将用户输入的数据渲染到模板前,应该进行充分的验证和转义。
- 严格控制服务器端传递给前端的数据,只发送必需的数据。
掌握以上方案和技巧,能够解决 EJS 和 Plotly 协同工作时的各种问题,使 Web 开发流程更顺畅、代码结构更规范,并确保 Web 应用的安全性。