【学习笔记】JS 在循环中设置监听事件并使用 ajax 设置动态添加的元素的值时出现的问题及其解决方案
作者:互联网
问题
for(var i = 1 ; i <= 10 ; i ++) { // 注意循环变量 i
var newLine = "<tr>";
newLine += "<td><input type='text' id='sampleInput" + i + "'></td>";
newLine += "<td><span id='sampleSpan" + i + "'></td>";
newLine += "</tr>";
// 动态为 newLine 追加 HTML,id 与循环变量有关
$("#sampleTable tbody").append(newLine);
// 往已存在的 table 中添加新的这一行
$("#sampleInput" + i).on("input", function(){ //这里设置的监听对象是没问题的,能够实现对于 sampleInput i 的监听
$.ajax({
type: "get",
url: "sampleAction",
// data: {}, 假装这里有传别的值
success: function(data){
// data = eval("(" + data + ")");
$("#sampleSpan" + i).html(data); // 这里想修改 sampleSpan i 的值
}
});
});
}
上面这一段 \(JS\) 代码,意图是往 \(sampleTable\) 中插入十行,每行一个文本框 \(sampleInput\{i\}\) 和一个行内元素 \(sampleSpan\{i\}\)
然后对于每行的文本框,只要触发了 \(input\) 事件就向后台发送请求,将获取到的数据在同一行的行内元素上显示出来
但这段代码的事实却是,不论修改哪个文本框,行内元素都没有效果
实际上在 \(ajax\) 的 \(success\) 匿名函数里看看 \(i\) 的值就清楚了,加一行 \(alert\) 输出,发现所有 \(i\) 的值都是 \(11\)
这是因为 \(ajax\) 只有执行完请求且获得数据后才会执行 \(success\) 匿名函数,这一部分与循环是异步执行的,也就是说在执行这个函数的时候可能外头的 \(for\) 循环已经结束了(终值就是 \(11\))
而在函数内调用 \(i\) 这个变量是通过地址去取值的,并没有把执行 \(ajax\) 时的 \(i\) 的值缓存下来,才会出现上面的这种情况
这里可能有人会说,我直接把 \(ajax\) 的异步关了就是了 async: false
所以上面的例子里在外层套了个监听
监听事件触发的时候循环肯定是执行完了的,与这个异步没有关系
解决
解决方法,把需要的值通过 \(ajax\) 传给后端,让后端重新传回来,问题解决(简单粗暴)
因为传入值时还没有开始异步执行,引用的 \(i\) 是会缓存当时的值的
for(var i = 1 ; i <= 10 ; i ++) {
var newLine = "<tr>";
newLine += "<td><input type='text' id='sampleInput" + i + "'></td>";
newLine += "<td><span id='sampleSpan" + i + "'></td>";
newLine += "</tr>";
$("#sampleTable tbody").append(newLine);
$("#sampleInput" + i).on("input", function(){
$.ajax({
type: "get",
url: "sampleAction",
data: {id: i}, // 把需要的值 i 传给后端
success: function(data){
data = eval("(" + data + ")");
var i = data.id; // 让 action 再把它返回来就是了
$("#sampleSpan" + i).html(data.data);
}
});
});
}
后记:
挺奇妙的,在 debug 的时候竟然没有遇到“无法找到动态添加的元素”的问题
本来我是往这个方向想的,于是就舍弃了通过 id 来查找元素,换了其他麻烦的方法(相对位置检索大法)
然后重新回来看这个问题,越看越奇怪,于是输出了一下循环变量,直接豁然开朗……
标签:值时,function,success,newLine,JS,ajax,设置,data,监听 来源: https://www.cnblogs.com/stelayuri/p/16088829.html