双独立下拉选择框联动更新对应UFC选手KD图表的实现问题
问题核心原因
当前代码存在4个直接导致第二个下拉框联动失效的问题:
- 第二个下拉框绑定的
onchange事件触发optionsChanged函数,但代码中从未定义该函数,触发时会直接抛出函数未定义的引用错误 - 现有
visuals绘图函数硬编码了渲染目标为id=bar的容器,就算第二个下拉框能触发回调,图表也只会覆盖第一个卡片的内容,不会渲染到第二个卡片的bar2容器 optionChanged回调里每次触发都重复调用init,会导致下拉框选项被重复追加,产生冗余选项- 初始化逻辑仅完成了下拉选项渲染,没有在页面首次加载时触发第二个图表的默认渲染
修复方案
1. 改造通用绘图函数,支持指定渲染容器
复用现有绘图逻辑,新增容器入参,避免写两套重复的绘图代码,修改后的visuals函数如下:
/** * 渲染选手KD历史数据图表 * @param {string} fighter 选中的选手名称 * @param {string} containerId 图表挂载的DOM容器ID,默认渲染到第一个卡片的bar容器 */ function visuals(fighter, containerId = 'bar'){ console.log('selected fighter: ', fighter) d3.json(`http://127.0.0.1:5000/combined/${fighter}`).then( data => { const combinedData = data; const dateList = []; const kdList = []; for(let i = 0; i < combinedData.length; i++) { kdList.push(combinedData[i].avg_KD); dateList.push(combinedData[i].date); } const plotData = [ { x: dateList, y: kdList, type: 'histogram', marker: { color: '#C70039', line: { color: "rgba(255, 100, 102, 1)", width: 1 } }, } ]; const barLayout= { title: 'KD History', hovermode: "closest", xaxis: {title: 'Date'}, yaxis: {title:'KD'}, margin: {t:30} }; // 将图表渲染到指定容器 Plotly.newPlot(containerId, plotData, barLayout); }); }
2. 补全两个下拉框的变更回调
拆分两个下拉框的触发逻辑,分别对应渲染到两个图表容器,移除无意义的重复init调用:
// 第一个下拉框变更回调:渲染到第一个卡片的bar容器 function optionChanged(fighter) { visuals(fighter, 'bar'); // 如需更新第一个卡片的选手元数据,在此处添加对应逻辑即可 } // 第二个下拉框变更回调:渲染到第二个卡片的bar2容器 function optionsChanged(fighter) { visuals(fighter, 'bar2'); // 如需更新第二个卡片的选手元数据,在此处添加对应逻辑即可 }
3. 优化初始化逻辑
修改init函数,完成下拉选项渲染后自动加载默认选手的两个图表,避免重复渲染下拉选项:
function init() { d3.json("http://127.0.0.1:5000/fighters").then(fighterList => { // 渲染第一个下拉框选项 const dropdown1 = d3.select("#selDataset"); fighterList.forEach(fighterName => { dropdown1.append('option').text(fighterName) }) // 渲染第二个下拉框选项 const dropdown2 = d3.select("#selDataset1"); fighterList.forEach(fighterName => { dropdown2.append('option').text(fighterName) }) // 设置默认选中选手(默认取列表第一位) const defaultFighter = fighterList[0]; dropdown1.property('value', defaultFighter); dropdown2.property('value', defaultFighter); // 首次加载渲染两个默认图表 optionChanged(defaultFighter); optionsChanged(defaultFighter); }); } // 页面加载完成后执行初始化 init();
4. 确认HTML绑定配置
现有HTML的下拉框事件绑定无需修改,确认对应关系即可:
- 第一个下拉框
id="selDataset"绑定onchange="optionChanged(this.value)",对应渲染id="bar"的图表容器 - 第二个下拉框
id="selDataset1"绑定onchange="optionsChanged(this.value)",对应渲染id="bar2"的图表容器
注意事项
- 确保存放回调函数、初始化逻辑的JS文件,在存放
visuals绘图函数的JS文件之后引入,避免出现「visuals未定义」的报错 - 如果需要区分两个图表的样式、标题,只需要给
visuals函数新增对应的配置入参即可,无需重复编写两套绘图逻辑 - 必须移除原来
optionChanged函数里调用init()的逻辑,否则每次切换下拉选项都会重复追加下拉选项,造成选项冗余。
内容的提问来源于stack exchange,提问作者Immanuel Nii Odai Odarteifio
相关产品推荐
相关产品推荐

