我有以下代码:
$( '#parent' ).on( 'click', '.a .b .c,.a .b .d,.a .b .e', function(){ ... });
三个选择器,要清楚的是:
.a .b .c
.a .b .d
.a .b .e
我试图弄清楚是否有可能以某种方式减少它:
.a .b (.c,.d,.e)
而且我知道如何轻松地使用非实时查询(例如使用.find
),但我特别希望将此事件附加到$( '#parent' )
我有以下代码:
$( '#parent' ).on( 'click', '.a .b .c,.a .b .d,.a .b .e', function(){ ... });
三个选择器,要清楚的是:
.a .b .c
.a .b .d
.a .b .e
我试图弄清楚是否有可能以某种方式减少它:
.a .b (.c,.d,.e)
而且我知道如何轻松地使用非实时查询(例如使用.find
),但我特别希望将此事件附加到$( '#parent' )
如果有人想使用它,请从 OP 进行编辑:阅读下面我的评论中的警告
这是你要找的吗?http://forum.jquery.com/topic/feature-req-any-selector-filter
jQuery.expr[':'].any = function(el, i, match) {
return jQuery.find.matches(match[3], [el]).length > 0;
};
我不确定这是否可能,但我会尝试使用一些正则表达式来发挥创意:
$('#parent').on('click', 'c,d,e'.replace(/(\w+)/g, '.a.b.$1')
这个想法是事先创建选择器。
如果您可以控制类名是什么,则可以使用命名约定。而不是 .c、.d、.e 等,将它们命名为 .cd、.ce、.cf 等。然后您可以[class^="c-"]
用作选择器。
更具体地编辑:
$( '#parent' ).on( 'click', '.a .b [class|="c"] ...
感谢Felix,我自己回答了这个问题:
jQuery.expr[':'].matches = function( elem, index, match ){
return $( elem ).is( match[3] );
};
$( '#parent' ).on( 'click', '.a .b :matches( .c, .d, .e )', ... );
出于性能原因,应该稍微优化一下:
.a .b nodeTypeOrOtherSelector:matches( .c, .d, .e )
稍微简化选择器的一种方法是将.a .b
测试移动到回调中:
$( '#parent' ).on('click', '.c, .d, .e', function(){
if ($(this).closest('.a .b').length === 0) {
// not the right element
return;
}
// ...
});
但从性能或代码维护的角度来看,这是否是可取的,我不知道。
学习elclanrs的解决方案,您可以动态创建选择器:
var ancestors = '.a .b';
var selector = ancestors + ['.c', '.d', '.e'].join(', ' + ancestors);
除此之外,您无能为力。CSS 选择器不能以这种方式工作。
为什么不将公共.a .b
祖先选择器移动到目标上下文选择器中?这应该有效:
$('#parent .a .b').on('click', '.c, .d, .e', function(){ ... });
更新: @cwolves 正确地指出,这只适用于静态,.a .b
即在附加处理程序时出现在页面上,这首先违背了委托事件的目的。