我原来的问题我已经设法通过从这个网站拼凑出其他答案来回答(谢谢StackOverflow!) - 只是发布在这里以帮助其他人想知道。
我有一个现场活动,如:
function addValidator(selector, validator) {
// Add the selector and validator to a hash map
$(selector).live('change', validateTag);
}
表行的数量会随时变化,我不想将表创建代码与验证代码紧密结合。
后来另一个验证函数出现时并不了解第一个,我需要避免同一个实时选择器触发validateTag函数两次,这将聚合所有验证消息并呈现关于给定输入的单个UI。 / p>
所以 - 每当有人调用addValidator时,我需要实际上替换实时事件处理程序,或者更具体地说,扩展它的选择器(因为我仍然在调用validateTag,我只需要实时处理程序来覆盖更多的基础)。我将在下面发布我想出的答案,很高兴听到更多。
- 更新以澄清我在做什么
我有几个包含动态表的页面,可以包含任意数量的行。我不希望验证和表管理代码紧密耦合。我希望能够在表行中设置输入,如:
<input class="required email"/>
并且验证验证了forchange()的必需和电子邮件规则。在代码中:
Valid.addValidator('input.required', Valid.required);
Valid.addValidator('input.email', Valid.email);
显然,当添加和删除行时,我可以继续将事件重新应用到输入,但这会紧密耦合表生成器代码和验证代码。
另一个黑客只是构建一个单独的直播活动,如:
$('input, select, textarea').live('change', Valid.validateTag);
然后使用hashmap查找究竟适用于此特定标记的内容,但这假设我将验证的唯一内容是输入,选择和textareas,以及我唯一想要的验证做就是改变。
我真正想要的是让任何类型的验证规则与选择器匹配任何标签,而不需要上述任何一种。第二个黑客并不是太糟糕,但它是一个错误的假设,对于不使用这三个基本标签之一的自定义控件是不灵活的。
答案 0 :(得分:1)
您可以将现有事件类型('click')和原始处理程序(在本例中为validateTag
)传递给die()函数以删除处理程序。
答案 1 :(得分:1)
经过大量修修补补,并从其他答案中获取建议。
addRule: function(selector, validator) {
// Save the rule
Valid.rules.push({selector: selector, validator: validator});
// Hunt for an existing live selector from prev addRule calls and expand on it if need be
var existingLiveEvents = $(document).data('events');
if (existingLiveEvents.change) {
var existing = existingLiveEvents.change.find(function (item) { return item.origHandler == Valid.validateThis; });
if (existing) {
// Expand the selector to include past rules
selector = existing.selector + ', ' + selector;
// And kill off the old validate selector
$(existing.selector).die('change', Valid.validateThis);
}
}
$(selector).live('change', Valid.validateThis);
}
validateThis()使用jQuery .is()方法检查每个规则是否该规则受该规则影响,如果是,则运行验证器。
如果你仔细观察,那里也会有一个.find()从我做的数组库中调用 - 它会做你所期望的:迭代一个数组,直到你传入的比较器函数返回true。然后它将你停止的项目交给你,或者为空。
如果人们对这个库感兴趣,我很乐意考虑使用它来开源。 jQuery验证插件很有趣,但它似乎没有处理我正在使用的动态输入集。我的库中还有一些其他魔法可以根据规则集获取输入标签。
答案 2 :(得分:1)
也许您可以使用命名空间事件:
$(selector).live('change.namespace', validateTag);
$(selector).unbind('.namespace');
答案 3 :(得分:0)
也许可以尝试以下列方式解耦您的实现:
var Valid = (function(){
var supportedEvents = ['click', 'keyup', 'change'],
listeners = {};
for(var i=0; i<supportedEvents.length; ++i) {
listeners[supportedEvents[i]] = [];
}
function addListener(type, classes, fn) {
listeners[type].push({classes:classes, fn:fn});
}
$('.validate').live(supportedEvents.join(' '), function(e){
for(var i=0; i<listeners[e.type].length; ++i) {
if ($(this).hasClass(listeners[e.type][i].classes)) {
listeners[e.type][i].fn.call(this, e);
}
}
});
return {
supportedEvents: supportedEvents,
addListener: addListener
};
})();
工作示例:http://jsfiddle.net/4npzm/1/
注意:
.delegate
。.hasClass
,遍历可能的类),甚至是通配符(if (classes === '*' || other_match_patterns)
) {}
,而不是数组[]
,然后删除侦听器变得简单,并且可以单独完成而无需保留对函数的引用)这使得保持和引用事件处理程序的核心处理保持在您自己的代码范围内,而不是附加事件的方法,然后“失去对它们的控制”,这使得进一步处理变得困难 - 并且意味着你必须绑定和取消绑定...
这不是最终版本,只是功能的简要概述,虽然对我来说它看起来很直观和灵活。