我正在使用Judge gem构建简单的客户端边界。
一切都很完美,直到我选择在"模糊"上运行验证。而不是点击按钮。
脚本:
var divs = ["advertisement_age","advertisement_weight","advertisement_region_id","advertisement_height","advertisement_name","advertisement_phone_number","Record_Start_Time",
"Record_End_Time","Record_Start_Time2","Record_End_Time2","advertisement_description", "advertisement_description_ru", "advertisement_terms_of_service"];
var arrayLength = divs.length;
var error_count =0;
for (var i = 0; i < arrayLength; i++) {
$(document.getElementById(divs[i])).blur(function(){
judge.validate(document.getElementById(divs[i]), { // This line causes error
valid: function(element) {
element.style.border = '1px solid green';
},
invalid: function(element, messages) {
element.style.border = '1px solid red';
// alert(messages.join(','));
}
});
});
}
在Mozzila Firebug中,当我重新加载页面时,没有任何错误消息。 触发模糊事件时会出现错误。
错误讯息:
TypeError: this.element is null
this.attrValidators = root.JSON.parse(this.element.getAttribute('data-validate')...
如果该数组有效,我不明白为什么它会在第二个document.getElementById(divs[i])
而不是第一个崩溃?
有什么建议吗?
由于
答案 0 :(得分:2)
问题是,当blur
事件触发时,for
循环已退出,i
的值将设置为for
时的最后一个值{退出{1}}循环。然后,最终,blur
事件触发judge.validate(document.getElementById(divs[i])
将失败,因为i
不是您所期望的。修复它的一种方法是在i
:
for (var i = 0; i < arrayLength; i++) {
(function(index) { // index is the current i value
$(document.getElementById(divs[index])).blur(function() {
judge.validate(document.getElementById(divs[index]), {
valid: function(element) {
element.style.border = '1px solid green';
},
invalid: function(element, messages) {
element.style.border = '1px solid red';
// alert(messages.join(','));
}
});
});
})(i); // pass i to the immediately executing anonymous function (closure)
}
因此我们将$.blur
代码放在一个闭包中并传递i
。在闭包i
内将调用index
。 index
的值将是循环执行代码时的预期值,并且在循环退出后将保持该值。请注意blur
处理程序内部我们现在使用divs[index]
的方式。
要解决这个特殊问题的一点是,blur
事件处理函数是异步的,并且不会评估divs[i]
,直到模糊事件发生,这将发生在for
循环已退出,并将i
的值保留为其最后一个值i == arrayLength - 1
。
此处还有更多内容:Calling an asynchronous function within a for loop in JavaScript
解决此问题的另一种方法是使用document.getElementById(divs[i])
保存您找到的元素,然后在处理程序中使用this
:
for (var i = 0; i < arrayLength; i++) {
var field = $(document.getElementById(divs[i]));
field.blur(function() {
judge.validate(this, { // `this` is the field element
valid: function(element) {
element.style.border = '1px solid green';
},
invalid: function(element, messages) {
element.style.border = '1px solid red';
// alert(messages.join(','));
}
});
});
}
我选择后一种解决方案,因为它更清洁。只是想先解释封口的事情。