d3.js v4如何正确更新从CSV文件生成的HTML元素,解决更新混乱问题
问题根因
- 数据绑定未指定唯一key:d3默认按数组索引匹配元素,当CSV条目增减、顺序变化时,元素和数据的对应关系完全错乱,导致删错、更新错元素
- 元素更新逻辑错误:你将子元素创建逻辑和merge操作绑定,每次更新都会给已存在的条目重复追加子元素,或是错误覆盖原有子元素,最终导致布局混乱、非iframe元素消失
- 选择器范围过大:
selectAll("div")会选中容器下所有div,容易误匹配其他元素,进一步加剧逻辑错误 - 样式规则错误:你写的盒模型规则缺少通配符
*,导致元素宽高计算不符合预期,布局错位
修复方案
首先修正样式中的盒模型规则:
/* 原来的规则缺少*,现在补上 */ * { box-sizing: border-box; }
然后替换caixa_suspensa_5函数为以下实现,严格遵循d3 v4的enter/update/exit模式,区分新增元素和已有元素的操作:
function caixa_suspensa_5(data) { // 仅匹配条目容器div,指定唯一key绑定数据(若label不唯一可换为numbergame) let update_5 = select_5.selectAll("div.matches") .data(data, d => d.label); // 移除数据已不存在的条目 update_5.exit().remove(); // 仅给新增的条目创建完整的子元素结构 const newEntries = update_5.enter().append("div") .attr("class", "matches"); // 新增条目创建iframe newEntries.append("iframe") .style("width", "100%") .style("height", "282"); // 新增条目创建投注表单和按钮 newEntries.append("form") .attr("target", "_blank") .style("width", "100%") .append("input") .attr("type", "submit") .attr("target", "_blank") .style("width", "100%") .attr("value", "Jogo Betfair"); // 新增条目创建图表输入框 newEntries.append("form") .append("input") .attr("type", "text") .style("width", "100%"); // 新增条目创建logo图片 newEntries.append("img") .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 allEntries = update_5.merge(newEntries); allEntries.select("iframe") .attr("src", d => valorparaiframe(d.value)); allEntries.select("form:first-of-type") .attr("action", d => d.market); allEntries.select("form:last-of-type input") .attr("id", d => "barra-de-texto-para-grafico-" + d.numbergame); allEntries.select("img") .attr("name", d => "grafico-betfair-" + d.numbergame); }
如果需要实现真正的60秒更新,把setInterval(refresh_csv, 30000)的30000改为60000即可。
内容的提问来源于stack exchange,提问作者Digital Farmer
相关产品推荐
相关产品推荐

