使用HTMX发起GET请求加载含Chart.js画布的HTML片段时图表无法渲染的问题咨询
完全可以实现!问题出在脚本加载顺序和执行时机上
你的思路是对的——用HTMX异步加载包含Chart.js画布的HTML片段完全可行,只是当前代码里的脚本加载逻辑有问题,导致图表初始化代码执行时Chart对象还没准备好。
问题分析
你把Chart.js的核心库放在了异步加载的HTML片段里,而<script>标签默认是异步加载的。这就导致片段里的图表初始化代码(new Chart(...))会在Chart.js核心库下载并解析完成之前执行,自然会抛出Chart is not defined的错误,图表也就生成不了。
另外,主页面里已经加载了Chart.js的依赖插件(adapter、hammer、zoom),但缺少核心的Chart.js库,这也会影响插件的正常工作。
修复步骤
1. 将Chart.js核心库移到主页面加载
把片段里的Chart.js引入脚本移到主页面的<body>末尾,确保在HTMX发起请求前,Chart对象就已经存在:
修改后的主页面代码:
<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script src="https://unpkg.com/htmx.org@1.6.1" integrity="sha384-tvG/2mnCFmGQzYC1Oh3qxQ7CkQ9kMzYjWZSNtrRZygHPDDqottzEJsqS4oUVodhW" crossorigin="anonymous"></script> <div id="mainAjax" class="slide-in-left-fade-in fade-me-out fade-in"> <button class="" hx-get="/data-viz/simple-chart" hx-target="#mainAjax" hx-swap="outerHTML swap:0.2s" hx-select="#mainAjax" hx-trigger="myEvent from:body"> Get canvas </button> </div> <script> document.body.addEventListener("myEvent", function(evt) { alert("trigger is working") }) </script> <!-- 先加载Chart.js核心库 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js" integrity="sha512-TW5s0IT/IppJtu76UbysrBH9Hy/5X41OTAbQuffZFU6lQ1rdcLHzpU5BzVvr/YFykoiMYZVWlr/PX1mDcfM9Qg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <!-- 再加载依赖插件 --> <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.2.0/chartjs-plugin-zoom.min.js" integrity="sha512-TT0wAMqqtjXVzpc48sI0G84rBP+oTkBZPgeRYIOVRGUdwJsyS3WPipsNh///ay2LJ+onCM23tipnz6EvEy2/UA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> </body> </html>
2. 移除片段里的Chart.js引入
因为主页面已经加载了核心库,片段里不需要重复引入,避免冗余和潜在的加载冲突:
修改后的HTML片段代码:
<div id="mainAjax" class=""> <canvas class="my-4 w-100 chartjs-render-monitor" id="myChart" width="1110" height="468" style="display: block; height: 521px; width: 1234px;"></canvas> <script> const ctx = document.getElementById('myChart').getContext('2d'); var config = { type: 'line', data: { labels : ['2005-03-31', '2005-06-30', '2005-09-30', '2005-12-31', '2006-03-31', '2006-06-30', '2006-09-30', '2006-12-31', '2007-03-31', '2007-06-30', '2007-09-30', '2007-12-31', '2008-03-31', '2008-06-30', '2008-09-30', '2008-12-31', '2009-03-31', '2009-06-30', '2009-09-30', '2009-12-31', '2010-03-31', '2010-06-30', '2010-09-30', '2010-12-31', '2011-03-31', '2011-06-30', '2011-09-30', '2011-12-31', '2012-03-31', '2012-06-30', '2012-09-30', '2012-12-31', '2013-03-31', '2013-06-30', '2013-09-30', '2013-12-31', '2014-03-31', '2014-06-30', '2014-09-30', '2014-12-31', '2015-03-31', '2015-06-30', '2015-09-30', '2015-12-31', '2016-03-31', '2016-06-30', '2016-09-30', '2016-12-31', '2017-03-31', '2017-06-30', '2017-09-30', '2017-12-31', '2018-03-31', '2018-06-30', '2018-09-30', '2018-12-31', '2019-03-31', '2019-06-30', '2019-09-30', '2019-12-31', '2020-03-31', '2020-06-30', '2020-09-30', '2020-12-31', '2021-03-31', '2021-06-30', '2021-09-30'], datasets: [{ label: 'AAPL Revenue', lineTension: 0, data: [3243.0, 3520.0, 3678.0, 5749.0, 4359.0, 4370.0, 4837.0, 7115.0, 5264.0, 5410.0, 6789.0, 9608.0, 7512.0, 7464.0, 12907.0, 11880.0, 9084.0, 9734.0, 12207.0, 15683.0, 13499.0, 15700.0, 20343.0, 26741.0, 24667.0, 28571.0, 28270.0, 46333.0, 39186.0, 35023.0, 35966.0, 54512.0, 43603.0, 35323.0, 37472.0, 57594.0, 45646.0, 37432.0, 42123.0, 74599.0, 58010.0, 49605.0, 51501.0, 75872.0, 50557.0, 42358.0, 46852.0, 78351.0, 52896.0, 45408.0, 52579.0, 88293.0, 61137.0, 53265.0, 62900.0, 84310.0, 58015.0, 53809.0, 64040.0, 91819.0, 58313.0, 59685.0, 64698.0, 111439.0, 89584.0, 81434.0, 83360.0], backgroundColor: '#A3BE8C4D', fill: false, showLine : true, borderColor: '#A3BE8C' , borderWidth: 1 }], }, } var myChart = new Chart(ctx, config); console.log(myChart.data.datasets) document.body.addEventListener("cart-updated", function (evt) { alert("cart updated") }) </script> </div>
3. 额外注意事项
- HTMX会自动执行加载的HTML片段中的
<script>标签,所以不需要额外手动触发代码执行。 - 如果后续需要动态更新图表数据,可以通过HTMX的事件(比如
htmx:afterSwap)来监听内容加载完成,再执行更新逻辑。 - 确保所有Chart.js的依赖插件(adapter、zoom等)都在核心库之后加载,这是Chart.js插件的要求。
这样修改后,当你点击按钮触发HTMX请求时,加载的片段里的初始化代码就能正常访问到已经加载好的Chart对象,图表也就会正确渲染出来了。
内容的提问来源于stack exchange,提问作者Paul Marmagne
相关产品推荐
相关产品推荐

