# 二、选择

## 自定义 jQuery 过滤器在单独使用时可以选择元素

没有必要提供与过滤器结合的实际元件，例如`$('div:hidden')`。在任何需要选择器表达式的地方，都可以简单地单独通过过滤器。

一些例子:

```js
// Selects all hidden elements
$(':hidden');
// Selects all div elements,
then selects only even elements 
$('div').filter(':even');

```

## 摸索着`:hidden`和`:visible`滤镜

定制的 jQuery 选择器过滤器 **`:hidden`** 和 **`:visible`** 并没有像预期的那样考虑 CSS 可见性属性。jQuery 确定一个元素是隐藏还是可见的方法是该元素是否占用文档中的任何空间。确切地说，如果浏览器报告的 **`offsetWidth`** 或 **`offsetHeight`** 大于 0，则元素可见。这样，一个元素中包含的 CSS **`display`** 值为 **`block`** 的元素，如果包含的 CSS**`display`**值为 **`none`** 的元素，就会准确地报告它不可见。

仔细检查代码，确保您理解为什么返回的值是 **`true`** ，尽管所选的 **`<div>`** 具有 **`display:block`** 的内嵌样式。

样本:sample22.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <div id="parentDiv" style="display: none;">
        <div id="childDiv" style="display: block;"></div>
    </div>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>  (function($){     
            //
Returns true because the parent div is hidden, so the     
            //
encapsulated div reports zero offsetWidth and offsetHeight.     
      alert($('#childDiv').is(':hidden'));
  })(jQuery); </script>
</body>
</html>

```

## 使用`is()`方法返回一个布尔值

通常需要确定所选的元素集是否包含特定的元素。使用 **`is()`** 方法，我们可以对照表达式/过滤器检查当前设置。如果集合包含至少一个由给定表达式/过滤器选择的元素，检查将返回 **`true`** 。如果它不包含元素，则返回一个 **`false`** 值。检查以下代码:

样本:sample23.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <div id="i0">jQuery</div>
    <div id="i1">jQuery</div>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>  (function($){     
      // Returns true.     
      alert($('div').is('#i1'));      
      // Returns false.
Wrapper set contains no <div> with id="i2".     
      alert($('div').is('#i2'));      
      // Returns false.
Wrapper set contains no hidden <div>     
      alert($('div').is(':hidden'));
  })(jQuery); </script>
</body>
</html>

```

应该很明显，第二个 **`alert()`** 将返回 false 值，因为我们的包装器集不包含 **`<div>`** ，该包装器集具有 **`id`** 属性值 **`i2`** 。 **`is()`** 方法对于确定包装集是否包含特定元素非常方便。

注释:

从 jQuery 1.3 开始， **`is()`** 方法支持所有表达式。以前，包含层次选择器的复杂表达式(如**`+`****`~`**【和 **`>`** )总是返回 **`true`** 。

过滤器由其他内部 jQuery 函数使用。因此，适用于那里的所有规则也适用于这里。

一些开发人员使用 **`is('.class')`** 来确定一个元素是否有特定的类。不要忘了 jQuery 已经有一个这样做的方法叫做 **`hasClass('class')`** ，可以用在包含多个类值的元素上。但实话实说， **`hasClass()`** 只是 **`is()`** 法的一种便捷包装。

## 可以传递 jQuery 多个选择器表达式

您可以为 jQuery 函数的第一个参数提供几个用逗号分隔的表达式: **`$('expression, expression, expression')`** 。换句话说，您不局限于仅使用单个表达式来选择元素。例如，在下面的例子中，我传递了 jQuery 函数的三个表达式，用逗号分隔。

样本:sample24.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <div>jQuery </div>
    <p>is the </p>
    <ul>
        <li>best!</li>
    </ul>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>  (function ($) {
      // Alerts jQuery is
the best!     
      alert($('div,
p, li').text());       
      // Inefficient way.
Alerts jQuery is the best!     
      alert($('div').text() + $('p').text() + $('li').text());
  })(jQuery); </script>
</body>
</html>

```

这些表达式中的每一个都选择了全部添加到包装器集中的 DOM 元素。然后，我们可以使用 jQuery 方法对这些元素进行操作。请记住，所有选定的元素都将放在同一个包装器集中。一种低效的方法是调用三次 jQuery 函数，每个表达式调用一次。

## 检查面皮设置`.length` 以确定选择

通过检查包装集是否有长度，可以确定表达式是否选择了任何内容。您可以通过使用数组属性 **`length`** 来实现。如果 **`length`** 属性不返回 0，那么您知道至少有一个元素与您传递给 jQuery 函数的表达式匹配。例如，在下面的代码中，我们检查页面中有一个元素的 **`id`** 为“无”你猜怎么着？它不在那里！

样本:sample25.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>  (function($){     
      // Alerts
"0".     
      alert($('#notHere').length);
  })(jQuery); </script>
</body>
</html>

```

注意事项:

如果不明显，length 属性还可以报告包装器集中的元素数量——换句话说，传递给 jQuery 函数的表达式选择了多少元素。

## 创建用于选择元素的自定义过滤器

jQuery 选择器引擎的功能可以通过创建自己的自定义过滤器来扩展。理论上，您在这里所做的就是构建已经是 jQuery 一部分的自定义选择器。例如，假设我们想要选择网页上绝对定位的所有元素。由于 jQuery 还没有自定义的 **`:positionAbsolute`** 过滤器，我们可以创建自己的过滤器。

样本:sample26.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <div style="position: absolute">absolute</div>
    <span style="position: absolute">absolute</span>
    <div>static</div>
    <div style="position: absolute">absolute</div>
    <div>static</div>
    <span style="position: absolute">absolute</span>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script> (function ($) {
     // Define custom filter by
extending $.expr[':']     
     $.expr[':'].positionAbsolute
= function (element)
     { return $(element).css('position') === 'absolute'; };
     // How many elements in the
page are absolutely positioned?     
     alert($(':positionAbsolute').length); //
Alerts "4"      
     // How many div elements are
absolutely positioned?     
     alert($('div:positionAbsolute').length); //
Alerts "2". 
 })(jQuery); </script>
</body>
</html>

```

这里要把握的最重要的一点是，你不局限于 jQuery 提供的默认选择器。你可以自己创造。然而，在您花时间创建自己版本的选择器之前，您可能只需简单地尝试具有指定过滤功能的 **`filter()`** 方法。例如，我可以通过简单地用传递给 **`filter()`** 方法的函数过滤前面例子中的 **`<div>`** 元素来避免编写 **`:positionAbsolute`** 选择器。

```js
// Remove <div>
elements from the wrapper 
// set that are not
absolutely positioned 
$('div').filter(function () { return $(this).css('position') === 'absolute'; });
// or  
// Remove all elements from
the wrapper 
// set that are not
absolutely positioned 
$('*').filter(function () { return
$(this).css('position') === 'absolute'; });

```

注释:

有关创建自己的选择器的更多信息，我建议阅读以下内容:

[http://www . benna del . com/blog/1457-How-Build-A-Custom-jQuery-selector . htm](http://www.bennadel.com/blog/1457-How-To-Build-A-Custom-jQuery-Selector.htm)

## 按数字顺序过滤与 DOM 关系的区别

jQuery 提供过滤器，用于根据集合中元素的数字上下文过滤包装器集合。

这些过滤器是:

*   :首先
*   :最后
*   :偶数
*   :奇怪
*   :eq(指数)
*   :gt(索引)
*   :lt(索引)

注释:

筛选包装器集本身的筛选器是通过从起点 0 或索引 0 开始筛选包装器集中的元素来实现的。例如**`:eq(0)`****`:first`**访问集合中的第一个元素—**`$('div:eq(0)')`**—该元素的索引为 0。这与单索引的 **`:nth-child`** 过滤器形成对比。意为，例如， **`:nth-child(1)`** 会返回第一个子元素，但试图使用 **`:nth-child(0)`** 将不起作用。使用 **`:nth-child(0)`** 将始终选择无。

使用 **`:`** `first`将选择集合中的第一个元素，而 **`:`** `last`将选择集合中的最后一个元素。请记住，它们根据集合中的关系(从 0 开始的数字层次结构)过滤集合，而不是 DOM 上下文中的元素关系。有了这些知识，应该很明显为什么过滤器**`:first`****`:last`**和 **`:eq(index)`总是返回单个元素。**

如果不明显，请允许我进一步解释。 **`:`** `first`之所以只能返回单个元素，是因为只有一个集合时，一个集合中只能有一个元素被首先考虑。这应该是相当符合逻辑的。检查下面的代码，看看这个概念是如何运作的。

样本:sample27.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <ul>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li>9</li>
        <li>10</li>
    </ul>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script> (function ($) {
     // Remember that text()
combines the contents of all 
     // elements in the wrapper
set into a single string. 
     alert('there
are '
+ $('li').length + ' elements in the set');
     // Get me the first element
in the set. 
     alert($('li:first').text()); //
Alerts "1".  
     // Get me the last element
in the set. 
     alert($('li:last').text()); //
Alerts "10"  
     // Get me the 6th element in
the set, 0 based index. 
     alert($('li:eq(5)').text()); //
Alerts "6".  
 })(jQuery); </script>
</body>
</html>

```

有了对操纵集合本身的清晰理解，我们可以通过使用过滤器来增强我们对选择元素的理解，这些过滤器选择与实际 DOM 中的其他元素具有唯一关系的元素。jQuery 为此提供了几个选择器。其中一些选择器是自定义的，而一些是用于选择 DOM 元素的众所周知的 CSS 表达式。

*   祖先后裔
*   父>子
*   上一个+下一个
*   前一兄弟姐妹
*   :第 n 个子代(选择器)
*   :第一个孩子
*   :最后一个孩子
*   :独生子女
*   :空
*   :has(选择器)
*   :家长

使用这些选择器过滤器将根据元素在 DOM 中与 DOM 中其他元素的关系来选择元素。为了演示这个概念，让我们看一些代码。

样本:sample28.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script> (function ($) {
     // Remember that text()
combines the contents of all 
     // elements in the wrapper
set into a single string. 
     alert($('li:nth-child(2)').text()); //
Alerts "22". 
     alert($('li:nth-child(odd)').text()); //
Alerts "135135". 
     alert($('li:nth-child(even)').text()); //
Alerts "2424". 
     alert($('li:nth-child(2n)').text()); //
Alerts "2424".  
 })(jQuery); </script>
</body>
</html>

```

如果你对 **`$('li:nth-child(odd)').text()`** 返回值 135135 感到惊讶，那你还没有摸索到关系过滤器。该声明中， **`$('li:nth-child(odd)')`** 口头表示将“在网页中找到所有 **`<li>`** 子元素，然后通过奇数子元素进行过滤。”嗯，碰巧页面中有两个结构有一组由 **`<li>`** 组成的兄弟结构。我的观点是:包装器集由基于过滤器的元素组成，该过滤器考虑了一个元素与 DOM 中其他元素的关系。这些关系可以在多个位置找到。

要带走的概念是，并非所有过滤器都是平等创建的。确保您了解哪些是基于 DOM 关系进行过滤的，例如 **`:only-child`** ，哪些是根据元素在包装集中的位置进行过滤的，例如 **`:eq()`** 。

## 当值包含元字符时，通过`id`选择元素

jQuery 选择器使用一组元字符(例如 **`# ~ [] = >`** )，当用作名称的字面部分时(例如 **`id="#foo[bar]"`** )应该被转义。可以通过在字符前加两个反斜杠来转义字符。检查下面的代码，看看在选择表达式中使用两个反斜杠如何允许我们选择 id 属性值为 **`#foo[bar]`** 的元素。

样本:sample29.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <div id="#foo[bar]">jQuery</div>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>  (function ($) {
      // Alerts
"jQuery"     
      alert($('#\\#foo\\[bar\\]').text());
  })(jQuery);
    </script>
</body>
</html>

```

以下是用作名称的文字部分时需要转义的字符的完整列表。

| 

*   #
*   ；
*   &

*   。
*   +
*   *
*   ~
*   '
*   ：
*   "

 | 

*   ！
*   ^
*   $
*   [
*   ]
*   （
*   )
*   =
*   >
*   &#124;
*   /

 |

## 堆叠选择器过滤器

可以堆叠选择器过滤器，例如 **`a[title="jQuery"][href^="http://"]`** 。这方面的一个明显的例子是选择一个具有特定属性值的特定属性的元素。例如，下面的 jQuery 代码将只选择 HTML 页面中的 **`<a>`** 元素:

*   包含起始值为“http://”的`href`属性
*   具有值为“jQuery”的`title`属性

只有一个 **`<a>`** 被选中。

样本:sample30.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <a title="jQuery">jQuery.com</a>

    <a href="http://www.jquery.com" title="jQuery" class="foo">jQuery.com 1</a>

    <a href="">jQuery.com</a>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>
        (function ($) {
            //
Alerts "1"     
            alert($('a[title="jQuery"][href^="http://"]').length);
        })(jQuery);
    </script>
</body>
</html>

```

注意代码中我们是如何堆叠两个过滤器来完成这个选择的。

除了属性过滤器之外，还可以堆叠其他选择器过滤器。例如:

```js
// Select the last
<div> contained in the 
// wrapper set that contains
the text "jQuery". 
$('div:last:contains("jQuery")')
// Get all check boxes that
are both visible and selected. 
$(':checkbox:visible:checked')

```

要带走的概念是选择器过滤器可以堆叠并组合使用。

## 嵌套选择器过滤器

选择器筛选器可以嵌套。这使您能够以非常简洁和强大的方式使用过滤器。下面，我举一个例子来说明如何嵌套过滤器来执行复杂的过滤。

样本:sample31.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <div>javascript</div>
    <div><span class="jQuery">jQuery</span></div>
    <div>javascript</div>
    <div><span class="jQuery">jQuery</span></div>
    <div>javascript</div>
    <div><span class="jQuery">jQuery</span></div>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script> (function ($) {
     // Select all div's, remove
all div's that have a child element with class="jQuery". 
     alert($('div:not(:has(.jQuery))').text()); //
Alerts combined text of all div's.  
     // Select all div's, remove
all div's that are odd in the set (count starts at 0).  
     alert($('div:not(:odd)').text()); //
Alerts combined text of all div's.  
 })(jQuery); </script>
</body>
</html>

```

要带走的概念是选择器过滤器可以嵌套。

注释:

您还可以嵌套和堆叠过滤器，例如 **`$('p').filter(':not(:first):not(:last)')`** 。

## 摸索着`:nth-child()` 滤镜

**`:nth-child()`** 滤镜有很多用途。例如，假设您只想选择包含在 **`<ul>`** 元素中的每三个`<li>`元素。使用`:nth-child()`过滤器是可能的。检查以下代码，以更好地理解如何使用`:nth-child()`过滤器。

样本:sample32.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li>9</li>
        <li>10</li>
    </ul>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script> (function ($) {
     // Remember that text()
combines the contents of all 
     // elements in the wrapper
set into a single string.  
     // By index. 
     alert($('li:nth-child(1)').text()); //
Alerts "1".  
     // By even. 
     alert($('li:nth-child(even)').text()); //
Alerts "246810".  
     // By odd. 
     alert($('li:nth-child(odd)').text()); //
Alerts "13579".  
     // By equation. 
     alert($('li:nth-child(3n)').text()); //
Alerts "369".  
     // Remember this filter uses
a 1 index. 
     alert($('li:nth-child(0)').text()); //
Alerts nothing. There is no 0 index.  
 })(jQuery); </script>
</body>
</html>

```

## 通过使用正则表达式搜索属性值来选择元素

当用于选择元素的 jQuery 属性过滤器不够健壮时，请尝试使用正则表达式。James Padolsey 为过滤器选择器编写了一个很好的 [扩展](http://james.padolsey.com/javascript/regex-selector-for-jquery/)，它将允许我们为过滤创建自定义正则表达式。我在这里提供了一个代码示例，但是请确保您也查看了关于[【http://james.padolsey.com】](http://james.padolsey.com)的文章，了解所有详细信息。

样本:sample33.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <div id="123"></div>
    <div id="oneTwoThree"></div>
    <div id="0"></div>
    <div id="zero"><div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>  (function ($) {
      //James Padolsey
filter extension. 
      jQuery.expr[':'].regex = function (elem, index,
match) {
          var matchParams =
match[3].split(','), validLabels = /^(data|css):/, attr = {
method: matchParams[0].match(validLabels) ? matchParams[0].split(':')[0] : 'attr', property:
matchParams.shift().replace(validLabels, '') }, regexFlags =
'ig', regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g, ''), regexFlags);
          return
regex.test(jQuery(elem)[attr.method](attr.property));
      }
      // Select div's where
the id attribute contains numbers. 
      alert($('div:regex(id,[0-9])').length); //
Alerts "2".  
      // Select div's where
the id attribute contains the string "Two". 
      alert($('div:regex(id,
Two)').length);
// Alerts "1".
  })(jQuery); </script>
</body>
</html>

```

## 选择直系子女与所有后代的区别

直接子元素只能通过使用组合器`>` 或通过`children()`遍历方法来选择。可以使用`*` CSS 表达式选择所有后代。确保你清楚地理解两者之间的区别。下面的例子演示了不同之处。

样本:sample34.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <div>
        <p><strong><span>text</span></strong></p>
        <p><strong><span>text</span></strong></p>
    </div>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>  (function ($) {
      // Each statement
alerts "2" because there are 
      // two direct child
<p> elements inside of <div>. 
      alert($('div').children().length);
      // or 
      alert($('>*', 'div').length);
      alert($('div').find('>*').length);

      // Each statement
alerts 6 because the <div> contains 
      // 6 descendants, not
including the text node. 
      alert($('div').find('*').length);
      // or 
      alert($('*', 'div').length);
  })(jQuery); </script>
</body>
</html>

```

## 当已经设置了上下文时，选择直接子元素

当已经提供了上下文时，可以在没有上下文的情况下使用组合器 **`>`** 来选择直接的子元素。检查下面的代码。

样本:sample35.html

```js
<!DOCTYPE html>
<html lang="en">
<body>
    <ul id="firstUL">
        <li>text</li>
        <li>
            <ul id="secondUL">
                <li>text</li>
                <li>text</li>
            </ul>
        </li>
        <li>text</li>
    </ul>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>  (function ($) {
      // Select only the
direct <li> children. Alerts "3". 
      alert($('ul:first').find('>
li').length); 
// or 
      alert($('>
li',
'ul:first').length);
  }
      )(jQuery); </script>
</body>
</html>

```

基本上，当已经确定了上下文时，`'> element'`可以用作表达式。