如何读取CSV文件动态更新页面数据 替代固定DOM元素静态数据
问题原因梳理
d3.csv是异步接口,返回值为Promise对象,无法直接作为数组绑定到D3数据上- 同时引入D3 v4和D3 v7两个版本,存在API冲突
- 未添加缓存清除逻辑,浏览器会默认缓存CSV文件,导致服务端文件更新后前端仍读取旧数据
- 仅处理了数据新增的enter逻辑,未处理已有数据更新的场景,字段变更时无法同步更新DOM属性
修复后完整代码
<html> <head> <style> * { box-sizing: border-box; } .matches { text-align:center; float: left; width: 355px; border: 1px solid white; border-collapse: collapse; } .column { text-align:center; float: left; width: 355px; border: 1px solid white; border-collapse: collapse; } .grid { float: left; width: 1431px; } .row:after { content: ""; display: table; clear: both; } .button { background-color: #33ccff; color: black; font-weight: bold; } input[type=submit] { background-color: #33ccff; color: black; font-weight: bold; } html { overflow: scroll; overflow-x: hidden; } ::-webkit-scrollbar { width: 0px; background: transparent; } ::-webkit-scrollbar-thumb { background: #FF0000; } </style> <!-- 仅保留一个版本的D3,避免冲突 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.1.1/d3.min.js"></script> <script id="auto-update-images"> let interval_images window.addEventListener('DOMContentLoaded', () => { interval_images = setInterval(refresh_images, 1000); }) function refresh_images() { if (!document.images) return; const totalimages = document.querySelectorAll("img").length - 1; const lastimages = parseInt(document.getElementsByTagName('img')[totalimages].getAttribute('name').replace("grafico-betfair-", "")) + 1; for (let i = 1; i < lastimages; i++) { try { document.images['grafico-betfair-' + i].src = document.getElementById('barra-de-texto-para-grafico-' + i).value; } catch (e) { } } } </script> <script id="random-number"> function generateRandomIntegerInRange(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } </script> </head> <body style="background-color:black;"> <div style="color:white;font-weight:bold;overflow:hidden;overflow-y:scroll;" class="grid games" id="Lista-de-Jogos-Lateral"> <script id="script-da-caixa-de-selecao-suspensa-5"> var select_5 = d3.select("#Lista-de-Jogos-Lateral") .append("div") .attr("id","select-box-5") .style("width","100%") .style("max-height","574px"); // 改为异步函数处理异步CSV请求 async function update() { // 添加时间戳参数避免缓存,等待请求返回数据 let data = await d3.csv(`Lista_de_Jogos.csv?t=${Date.now()}`); let update_5 = select_5.selectAll(".matches") .data(data,d=>d.label); // 移除不存在的条目 update_5.exit().remove(); // 新增条目 const enter = update_5.enter() .append("div") .attr("class","matches") enter.append("form") .attr("target","_blank") .style("width","100%") .append("input") .attr("type","submit") .attr("target","_blank") .style("width","100%") .attr("value","Jogo Betfair"); enter.append("form") .append("input") .attr("type","text") .style("width","100%"); enter.append("img") .attr("type","text") .attr("src","https://sitedeapostas-com.imgix.net/assets/local/Company/logos/betfair_logo_transp.png?auto=compress%2Cformat&fit=clip&q=75&w=263&s=c1691b4034fd0c4526d27ffe8b1e839c"); // 合并新增和已有的条目,统一更新属性 const allMatches = update_5.merge(enter); allMatches.select('form:first-child') .attr("action",d => d.market); allMatches.select('form:nth-child(2) input') .attr("id",d => "barra-de-texto-para-grafico-" + d.numbergame) .attr("value", d=>d.label); allMatches.select('img') .attr("name",d => "grafico-betfair-" + d.numbergame); } update(); setInterval(update,2000); </script> </div> </body> </html>
部署注意事项
- 确保
Lista_de_Jogos.csv文件和HTML页面放在同一级目录下,路径不一致时自行修改d3.csv()中的路径参数 - 必须通过HTTP/HTTPS服务访问页面,不能直接打开本地HTML文件,浏览器跨域限制会禁止读取本地文件
- 可根据实际需求调整更新频率,CSV每分钟更新的情况下,不需要每2秒请求一次,可调整为30秒请求一次减少服务端压力
内容的提问来源于stack exchange,提问作者Digital Farmer
相关产品推荐
相关产品推荐

