使用D3.js批量请求JSON并绑定数据至Select元素的异常问题
问题修复:D3.js仅最后一个Select元素加载选项
核心问题
你的代码里obj、opt_table等变量未用let/const声明,属于全局变量。由于d3.json是异步请求,当回调函数执行时,循环已经跑完,所有回调里的obj都会指向最后一个select元素,最终只有最后一个select能加载选项。
修复方案
在循环内部用let/const声明所有局部变量,创建块级作用域,让每个异步回调都能引用当前循环迭代对应的元素。
修正后的完整代码
function attach_options() { const opts = d3.selectAll("select[data-opt-table]") opts.each(function(p,j) { const obj = d3.select(this) const opt_table = obj.attr('data-opt-table') const opt_field = obj.attr('data-opt-field') const opt_disp = obj.attr('data-opt-disp') const opt_lookup = obj.attr('data-opt-lookup') d3.json("{% url 'get-opts' %}" + opt_table + '/' + opt_field + '/' + opt_disp + '/' + opt_lookup + '/').then( function(data) { const options = obj.selectAll('option').data(data.opt_list) options.join('option') .attr('value', d => d.pk) .text(d => d.disp_value) } ) }) }
补充说明
- 用
const声明无需重新赋值的变量,let声明可能变更的变量,避免全局变量污染; - 块级作用域确保每个循环迭代的变量独立,异步回调触发时能精准指向当前处理的
select元素; - 建议给所有变量添加声明,养成规范的编码习惯,减少类似闭包陷阱问题。
内容的提问来源于stack exchange,提问作者Carl Peterson
相关产品推荐
相关产品推荐

