jQuery获取数据后C3图表仅最后一个渲染的问题求助
问题排查与解决方案
你遇到的这个问题,核心原因是使用innerHTML +=动态添加DOM元素时,会重新渲染整个父容器。每次执行document.getElementById("chartBlocks").innerHTML += ...,浏览器都会把chartBlocks里的所有内容重新解析一遍——之前已经绑定了C3图表的元素会被销毁再重建,但C3已经和原来的DOM节点绑定了,新生成的节点并没有被C3初始化,所以前面的图表就显示不出来;只有最后一次添加的元素因为是最后创建的,还没被覆盖,能正常渲染。
之前用for循环正常工作,应该是因为你当时没有用innerHTML +=的方式,而是直接创建元素并追加,或者是一次性渲染所有元素后再初始化图表。
下面给你两种具体的解决方案:
方案一:用createElement和appendChild添加元素(推荐)
这种方式不会重新渲染整个父容器,而是直接把新元素追加进去,原来的DOM节点不会被破坏,C3的绑定也能正常生效。修改你的代码如下:
$.getJSON('api/randomData?chartCount=' + chartsToMake).done( function(data) { // Extract list of servers from the data... var hostList = [] $.map(data, function(row) { hostList.push(row.host); }); // Make it a unique list var uniqueHostList = hostList.unique(); // 获取父容器 var chartBlocks = document.getElementById("chartBlocks"); // Iterate over the unique list of servers uniqueHostList.forEach( function(host) { var tag = "chart" + host.replace(/\./g, ""); var hostdata = data.filter( (v,i,a) => v.host === host) console.log("Processing Server:" + host + " with " + hostdata.length + " rows"); // 创建DOM元素并追加到父容器 var chartDiv = document.createElement('div'); chartDiv.id = tag.replaceAll('#',''); chartBlocks.appendChild(chartDiv); // Create the Chart here var chart = c3.generate({ bindto: "#" + tag, data: { json: hostdata, keys: { value: ['lowerband'] } } }); }); });
方案二:先批量创建所有DOM元素,再初始化图表
如果不想修改元素添加的方式,可以先把所有需要的div都用innerHTML +=创建好,然后再循环遍历这些div来初始化C3图表,这样就不会因为DOM重新渲染导致绑定失效:
$.getJSON('api/randomData?chartCount=' + chartsToMake).done( function(data) { // Extract list of servers from the data... var hostList = [] $.map(data, function(row) { hostList.push(row.host); }); // Make it a unique list var uniqueHostList = hostList.unique(); // 第一步:先创建所有DOM元素 var chartBlocks = document.getElementById("chartBlocks"); var html = ''; uniqueHostList.forEach( function(host) { var tag = "chart" + host.replace(/\./g, ""); html += "<div id=\"" + tag.replaceAll('#','') + "\"></div>"; }); chartBlocks.innerHTML = html; // 第二步:再循环初始化每个图表 uniqueHostList.forEach( function(host) { var tag = "chart" + host.replace(/\./g, ""); var hostdata = data.filter( (v,i,a) => v.host === host) console.log("Processing Server:" + host + " with " + hostdata.length + " rows"); var chart = c3.generate({ bindto: "#" + tag, data: { json: hostdata, keys: { value: ['lowerband'] } } }); }); });
这两种方案都能解决你遇到的问题,推荐第一种,因为它的DOM操作效率更高,也更符合现代前端的最佳实践。
内容的提问来源于stack exchange,提问作者Exie
相关产品推荐
相关产品推荐

