24

作为参考,这里有一篇关于使用 jQuery 创建自定义过滤器选择器的文章。


介绍:

对于那些不熟悉jQuery 的自定义过滤器选择器的人,这里有一个关于它们是什么的快速入门:

如果您需要一个可重用的,您可以通过将您自己的函数添加到对象filter来扩展 jQuery 的选择器表达式。jQuery.expr[':']

该函数将在当前集合中的每个元素上运行,并且应该返回 true 或 false(很像filter)。三位信息被传递给这个函数:

  1. 有问题的元素

  2. 该元素在整个集合中的索引

  3. 从正则表达式匹配返回的match数组,其中包含更复杂表达式的重要信息。

扩展jQuery.expr[':']后,您可以将其用作 jQuery 选择器中的过滤器,就像您使用任何内置的过滤器(:first:last:eq()


这是一个示例,我们将过滤分配有多个类的元素:

jQuery.expr[':'].hasMultipleClasses = function(elem, index, match) {
    return elem.className.split(' ').length > 1;
};

$('div:hasMultipleClasses');

这是小提琴:http: //jsfiddle.net/acTeJ/


在上面的示例中,我们没有使用match传入函数的数组。让我们尝试一个更复杂的例子。在这里,我们将创建一个过滤器来匹配tabindex大于指定数字的元素:

jQuery.expr[':'].tabindexAbove = function(elem, index, match) {
    return +elem.getAttribute('tabindex') > match[3];
};

$('input:tabindexAbove(4)');

这是小提琴:http: //jsfiddle.net/YCsCm/

之所以可行,是因为该match数组是从用于解析选择器的正则表达式返回的实际数组。因此,在我们的示例中,match将是以下数组

[":tabIndexAbove(4)", "tabIndexAbove", "", "4"]

如您所见,我们可以使用match[3].


问题:

在 jQuery 1.8 中,不再match数组传递给 filter 函数。由于我们无法访问传入的信息,因此tabindexAbove过滤器不再起作用(这个小提琴和上面那个小提琴之间的唯一区别是它使用了更高版本的 jQuery)。

所以,这里有几点我想澄清:

  1. 这是预期的行为吗?它在任何地方都有记录吗?

  2. 这是否与Sizzle已更新的事实有关(尽管它明确指出“在此重写中未更改 Sizzle 的旧 API”。也许这就是他们所说的“删除现在不必要的Sizzle.filter”) ?

  3. 现在我们无法访问match数组,还有其他方法可以获取传递给过滤器的信息(在我们的例子中,4)?

我从未在 jQuery Docs 中找到任何关于自定义过滤器选择器的文档,所以我不知道从哪里开始寻找有关此的信息。

4

2 回答 2

10

jQuery 添加了一个实用程序,用于在 Sizzle 中创建自定义伪。它有点冗长,但比使用 match[3] 更具可读性。它还具有性能更高的优点,因为您可以避免每次测试元素时重复繁琐的计算。已经被接受的答案是一个很好的答案,不过我加个注解说可以使用$.expr.createPseudo代替自己设置sizzleFilter属性,这样会节省一点空间。

jQuery.expr[':'].tabIndexAbove = $.expr.createPseudo(function( tabindex ) {
    return function(elem) {
        return +elem.getAttribute('tabindex') > tabindex;
    }
});

$('input:tabIndexAbove(4)').css('background', 'teal');

jsfiddle:http: //jsfiddle.net/timmywil/YCsCm/7/

这都记录在 Sizzle 的 github 上: https ://github.com/jquery/sizzle/wiki/Sizzle-Documentation

于 2012-08-06T18:45:20.520 回答
7

通过查看 jQuery 1.8 beta2 源代码和The New Sizzle的“可扩展性”部分,您必须设置fn.sizzleFiltertrue以获取伪参数和上下文。如果没有,您将只获得参数中的所有元素。

这是与您的示例执行相同操作的代码。使用selector函数中传递的参数来获取伪参数。

这是 jsfiddle 上的工作示例

正如上面的博文中提到的,您甚至可以预编译和缓存您的选择器。

var sizzle = jQuery.find;

var tabIndexAbove = function( selector, context, isXml ) {
    return function( elem ) {
        return elem.getAttribute("tabindex") > selector;
    };
};

/*
 fn.sizzleFilter is set to true to indicate that tabIndexAbove 
 is a function that will return a function for use by the compiler 
 and should be passed the pseudo argument, the context, and 
 whether or not the current context is xml. If this property is 
 not set, adding pseudos works similar to past versions of Sizzle
*/
tabIndexAbove.sizzleFilter = true;
sizzle.selectors.pseudos.tabIndexAbove = tabIndexAbove;

$('input:tabIndexAbove(4)').css('background', 'teal');

请注意,如果您正在查看源代码,jQuery 稍微改变了面向公众的接口指向的结构。

在 jQuery 1.7.2 中:

jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;

在 jQuery 1.8b2 中:

jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.pseudos;
于 2012-07-24T16:23:15.407 回答