使用D3与JavaScript过滤JSON数据报data.filter不是函数如何解决
问题原因
你收到Uncaught (in promise) TypeError: data.filter is not a function报错的核心原因是:
d3.json请求返回的data是旭日图所需的嵌套树形对象结构(根节点包含name、children等字段),而filter是JavaScript数组的专属原生方法,普通对象本身不支持该方法。- 你要过滤的是树形结构中携带
Periodo字段的节点,同时需要保留完整的层级关系才能正常渲染旭日图,不能直接对根对象使用数组过滤方法。
解决方案
你需要先实现一个递归过滤树形结构的工具函数,再调整原有逻辑适配过滤需求,同时可以优化数据请求逻辑避免重复拉取资源。
步骤1:实现树形结构递归过滤函数
/** * 递归过滤旭日图树形数据 * @param {object} node 要处理的树形节点 * @param {string} periodo 选中的过滤条件 * @returns {object|null} 符合条件的节点,不符合则返回null */ function filterTree(node, periodo) { // 选中「全部」时直接返回原节点不做过滤 if (periodo === "Todos") return node; // 当前节点携带Periodo字段且不符合条件,直接剔除该节点 if (node.Periodo && node.Periodo !== periodo) return null; // 存在子节点时递归过滤子节点 if (node.children) { const filteredChildren = node.children .map(child => filterTree(child, periodo)) .filter(Boolean); // 过滤掉不符合条件返回null的子节点 // 子节点全部被剔除时当前节点也无需保留,可根据业务需求调整该逻辑 if (filteredChildren.length === 0) return null; // 返回替换了子节点的新节点 return {...node, children: filteredChildren}; } // 没有子节点的叶子节点符合条件直接返回 return node; }
步骤2:调整业务逻辑代码
建议把数据请求和渲染逻辑拆分,避免每次切换选项都重复请求JSON文件:
// 缓存原始全量数据,避免重复请求 let fullData = null; // 页面加载时拉取一次全量数据,完成后首次渲染旭日图 d3.json("data/unicamp_ft.json").then(data => { fullData = data; renderSunburst(fullData); }); // 监听下拉框切换事件 $("#Selecionar-periodo").on("change", () => { // 数据还没加载完成时不执行操作 if (!fullData) return; const selectedPeriodo = $("#Selecionar-periodo").val(); const filteredData = filterTree(fullData, selectedPeriodo); // 过滤结果非空时重新渲染旭日图 if (filteredData) renderSunburst(filteredData); }); /** * 旭日图渲染函数,把你原有渲染逻辑封装到这里 * @param {object} data 渲染用的树形数据 */ function renderSunburst(data) { // 这里放你原有绘制可缩放旭日图的代码 // 注意:重新渲染前要清空原有SVG内容,或用D3的enter/update/exit模式处理更新,避免图表重叠 }
注意事项
如果你的Periodo字段只在特定层级的节点上存在,可以根据实际业务场景调整filterTree函数的判断逻辑,比如只过滤叶子节点、保留所有父层级节点等。
内容的提问来源于stack exchange,提问作者Jean Rogerio Franciscon
相关产品推荐
相关产品推荐

