动态生成依赖Select下拉框页面加载触发change时变量异常求助
问题:页面加载时预填充依赖下拉框的变量作用域问题
我有段时间没积极编程了,措辞可能不太准确,见谅。我用Flask从数据库生成select表单,数据库有值时预填充表单,无值则通过关联下拉框(选项同样来自数据库)补全。页面上有约11行动态生成的select,分两列:左列sel_dstColumn_XXX(XXX为数据库行ID)依赖右列sel_dstTable_XXX,每行的XXX一一对应。
已实现下拉框变更时的逻辑,代码如下:
$("select[id^=sel_dstTable]").change(function () { table = this.value; my_s = this.id.split('_')[2]; $.get("/get_columns/" + table, function (data, status) { var selID = "select[id=sel_dstColumn_" + my_s + "]"; $(selID).html(""); data.forEach(function (table) { $(selID).append("<option>" + table + "</option>"); }); }); });
对应的Python后端代码:
@app.route('/get_columns/<value>') def get_columns(value): if value in all_tables: return jsonify(all_tables[value]) return ''
这段变更逻辑虽有隐患,但单个字段处理时可正常使用。
现在需要在页面加载时,为所有sel_dstTable_XXX触发上述逻辑,预填充依赖的下拉框。但复制变更逻辑编写的初始化代码出现问题:变量my_s无法正确传入$.get()的回调函数,遍历.each()时,回调里的my_s始终获取最后一个行ID(如22),而非遍历到的12、13等ID。
当前初始化代码:
$(function () { $("select[name^=sel_dstTable_]").each(function () { table = this.value; my_s = this.id.split('_')[2]; console.log("expected variable my_s: " + my_s); $.get("/get_columns/" + table, function (data, status) { console.log("actual variable my_s:" + my_s); // var selID = "select[name=sel_dstColumn_" + my_s + "]"; // $(selID).html(""); // data.forEach(function (table) { // $(selID).append("<option>" + table + "</option>"); // }); }); }); });
控制台中expected能正确输出每个行ID,但回调里的actual全是最后一个ID。
解决方案:修复变量作用域问题
问题根源在于未用var/let声明变量,导致my_s和table成为全局变量。.each()循环执行速度远快于异步的$.get()回调,当回调执行时,全局的my_s已经被最后一次循环覆盖。
方法1:用let限定变量作用域
let会为每次循环迭代创建独立的作用域,确保回调能捕获当前迭代的变量值:
$(function () { $("select[name^=sel_dstTable_]").each(function () { let table = this.value; let my_s = this.id.split('_')[2]; console.log("expected variable my_s: " + my_s); $.get("/get_columns/" + table, function (data, status) { console.log("actual variable my_s:" + my_s); var selID = "select[id=sel_dstColumn_" + my_s + "]"; $(selID).html(""); data.forEach(function (col) { $(selID).append("<option>" + col + "</option>"); }); }); }); });
方法2:利用$.get()的上下文参数传递变量
将my_s作为上下文对象传入$.get(),回调中通过this访问:
$(function () { $("select[name^=sel_dstTable_]").each(function () { var table = this.value; var my_s = this.id.split('_')[2]; console.log("expected variable my_s: " + my_s); $.get("/get_columns/" + table, {}, function (data, status) { console.log("actual variable my_s:" + this.my_s); var selID = "select[id=sel_dstColumn_" + this.my_s + "]"; $(selID).html(""); data.forEach(function (col) { $(selID).append("<option>" + col + "</option>"); }); }, {my_s: my_s}); }); });
额外优化:修复变更事件的潜在问题
原变更事件代码同样存在全局变量污染的隐患,建议同步修改:
$("select[id^=sel_dstTable]").change(function () { let table = this.value; let my_s = this.id.split('_')[2]; $.get("/get_columns/" + table, function (data, status) { var selID = "select[id=sel_dstColumn_" + my_s + "]"; $(selID).html(""); data.forEach(function (col) { $(selID).append("<option>" + col + "</option>"); }); }); });
内容的提问来源于stack exchange,提问作者Scott W
相关产品推荐
相关产品推荐

