jQuery的包装集是一个非常重要的概念。包装集是指通过$("exp")
筛选出页面的一组满足表达式的元素,这一组元素就属于jQuery包装集中的元素。链式编程是jQuery的一大特点,而理解包装集是进行链式编程的基础。
研究jQuery包装集的一个重点是了解每一个包装集命令会返回什么结果,是返回原包装集还是返回新的包装集。关于这方面的描述将贯穿本文。
包装集的大小
jQuery的包装集和数组非常相似,可以使用length
属性来获取包装集的大小。另外,jQuery提供了一个size()
方法来获取包装集的大小。size()
命令的语法为:
方法 | 参数 | 返回值 | 描述 |
size() | 无 | 元素的个数(返回原包装集) | 返回包装集中元素的个数 |
例如我们想知道一个表格中的tr
元素的个数,可以使用下面的代码:
$("#table tr").size();
获取包装集中的元素
jQuery允许把包装集当做数组来使用,所以我们可以通过下标来获取包装集中的某个元素。另外,jQuery专门有一个get()
方法来获取包装集中的元素。get()
方法的语法为:
方法 | 参数 | 返回值 | 描述 |
get(index) | 参数index用于指定被返回的单个元素。如果没有指定这个参数,整个包装集以数组的方式返回 | 一个DOM元素和DOM元素数组(返回原包装集) | 获取包装集中的一个或所有的匹配元素。如果参数没有指定,包装集中的所有元素以js数组返回。如果指定了下标参数,就返回该下标指定的元素 |
例如要获取一个表格下标为2的tr
元素,可以使用下面的代码:
$($("#table tr").get(2))
注意,通过get()
方法返回的是JavaScript元素或JavaScript数组,不能够使用jQuery的方法。如果想使用jQuery的方法,需要使用$()
将它重新包装。
获取某个元素在包装集的位置
如果需要知道某个元素在包装集中的位置,可以使用index()
方法。index()
方法的语法为:
方法 | 参数 | 返回值 | 描述 |
index(element) | 参数element是元素的引用,用于确定元素的下标 | 元素在包装集中的下标。如果找不到该元素,则返回-1(返回原包装集) | 在包装集中查找某个元素,并返回该元素在包装集中的下标。如果没有找到该元素,则返回-1 |
往包装集中添加元素
当我们得到了一个包装集之后,如果想往这个包装集中再添加元素,可以使用add()
方法。add()
方法将多个选择器链接在一起,形成一个“或”的关系链。add()
方法的语法为:
方法 | 参数 | 返回值 | 描述 |
add(expression) | 参数expression可以是jQuery选择器、数组或元素,用于指定添加到包装集中的元素。如果它是jQuery选择器,则全部匹配元素都会被添加到集合中。如果是HTML片段,则创建适当的元素并添加到集合中。如果是DOM元素或DOM元素数组,则直接添加到集合中。 | 返回包装集(返回原包装集) | 将参数表达式指定的元素添加到包装集中。表达式可以是jQuery选择器、HTML片段、DOM元素或DOM元素数组 |
例如,如果有一个表格,我们在选择了表格的第一个td
元素之后,然后使用add()
方法在添加表格的最后一个td
元素到包装集中,并使它们的颜色变为绿色,代码如下:
$("#table tr td:first").add("#table tr td:last").addClass('success');
下图是一个返回结果的截图效果:
删除包装集中的某个元素
在确定了一个包装集之后,如果想将这个包装集中的某些元素取消掉,可以使用not()
方法。not()
方法的语法为:
方法 | 参数 | 返回值 | 描述 |
not(expression) | 参数expression可以是jQuery选择器、数组或元素,用于指定从包装集中删除的元素。 | 返回包装集(返回原包装集) | 根据表达式的值删除包装集中的元素。如果参数是jQuery选择器,则从包装集中删除所有匹配表达式的元素。如果参数是元素引用,则从包装集中删除该元素 |
例如,一个包装集为表格中的所有td
元素,通过not()
方法排除掉所有为2的倍数的td
元素,代码如下:
$("#table tr td").not("#table tr td:nth-child(2n)").addClass('success');
得到的效果如下图所示:
过滤包装集中的元素
jQuery的filter()
方法可以对包装集中的元素进行过滤。如果传给filter()
方法的参数是一个函数,那么会为每一个包装集元素反复调用这个函数,如果哪个元素的函数调用返回了false
,就删除那个元素。filter()
方法的语法为:
方法 | 参数 | 返回值 | 描述 |
filter(expression) | 参数expression可以是jQuery选择器或函数。如果是jQuery选择器,则从包装集中删除所有与选择器不匹配的元素。如果是函数,则用于确定筛选条件。它会为包装集中的每一个元素都调用一次该函数,以当前函数作为当前调用的上下文对象。函数返回false则从包装集中删除该元素。 | 返回包装集(返回原包装集) | 使用参数指定的jQuery选择器或筛选函数,删除包装集中指定的元素 |
获取包装集的子集
如果希望获取包装集中的某个子集,可以使用jQuery提供的slice()
方法。这个方法会创建并返回来自原包装集的任何连续的子包装集。slice()
方法的语法为:
方法 | 参数 | 返回值 | 描述 |
slice(begin,end) | 参数begin指定返回子包装集的第一个元素的下标(从0开始),end指定返回包装集的最后一个元素的下标,不包含end下标的元素(下标从0开始)。如果没有指定end,则表示从begin开始到包装集结束位置的子集 | 返回新的包装集 | 创建并返回新的包装集,新包装集是原包装集的连续子集 |
例如想要在一个表格的所有tr
元素中截取第二和第三个tr
元素,代码如下:
$("#table tr").slice(1,3).addClass('success');
得到的效果如下图所示:
通过关系获取包装集
jQuery允许我们根据DOM中包装元素与其它元素的层次关系,从现有包装集中获取新包装集。
根据关系来获取新包装集的方法有以下几个,这些方法都会返回新的包装集。
方法 | 返回值 | 描述 |
children() | 返回新的包装集 | 返回原包装集元素的所有唯一子元素所组成的包装集 |
contents() | 返回新的包装集 | 返回原包装集元素的内容的包装集,这些元素可能包含文本节点(该方法常用于获取<iframe> 元素的内容) |
next() | 返回新的包装集 | 返回原包装集元素的所有唯一的下一个兄弟元素所组成的包装集 |
nextAll() | 返回新的包装集 | 返回包含元素包装集元素的所有后续兄弟元素的包装集 |
parent() | 返回新的包装集 | 返回原包装集所有元素的唯一直接父元素的包装集 |
parents() | 返回新的包装集 | 返回原包装集所有元素的唯一祖先元素所组成的包装集,包括直接父元素和一直向上追溯的祖先元素,但不包括文档根元素 |
prev | 返回新的包装集 | 返回原包装集元素的所有唯一的上一个兄弟元素所组成的包装集 |
prevAll | 返回新的包装集 | 返回包含原包装集元素的所有前面兄弟元素的包装集 |
siblings() | 返回新的包装集 | 返回原包装集元素的所有唯一兄弟元素所组成的包装集 |
再次说明,上面的一组方法都会返回新的包装集。理解这些方法最好的办法就是自己动手写代码来进行测试。自己动手写一下代码测试一下这些方法吧!
find() 方法
find()
方法可以把现有的包装集搜索一遍,并返回包含所有匹配参数表达式元素的新包装集。find()
方法的语法为:
方法 | 参数 | 返回值 | 描述 |
find(selector) | 参数是一个jQuery选择器,元素必须和这个选择器匹配,才能成为包装集的一部分 | 返回新的包装集 | 返回包含原包装集和与选择器匹配的所有元素组成的新包装集。 |
find()
方法和filter()
方法在功能上有些类似,但是它们是不同的。这主要体现在:
- 1、
find()
方法返回新包装集,filter()
方法返回原包装集。 - 2、
find()
方法是在当前包装集的元素中去查找或过滤,而不是在包装集中过滤。而filter()
方法是在包装集中进行过滤。
如何理解上面的第2点呢?例如有一个表格,我们通过$('#table')
来获取了一个包装集,此时的包装集中只有一个元素(表格元素)。如果我们想在这个包装集来查找表格中的第2个tr
元素,就需要使用find()
方法,而不能使用filter()
方法。
$("#table").find("tr:eq(1)").addClass('success'); // 正确 $("#table").filter("tr:eq(1)").addClass('success'); // 错误
形象一点的比喻,调用find()
方法的包装集就好像一间大房子,我们现在只知道有一间大房子,想要在这间房子中查找某件东西。而调用filter()
方法的包装集是指我们已经知道了房子中的所有东西的明细,然后从这些东西中查找某样东西。
contains() 方法
contains(text)
方法用于查找包含text字符串的元素。这个方法也是返回新的包装集。contains(text)
方法的语法为:
方法 | 参数 | 返回值 | 描述 |
contains(text) | 参数text指定要添加到新包装集中的元素必须包含的文本字符串 | 返回新的包装集 | 返回由包含text参数所传入的文本字符串的元素所组成的新的包装集 |
除了上面介绍的方法之外,还有一个is()
方法,这个方法用于查看是否至少包含一个匹配给定选择器的元素。如果至少有一个元素匹配,就返回true
,否则返回false
。
链式编程
我们在上面的包装集介绍过程中,不断的提及每一个方法会返回什么包装集,是原有包装集还是新的包装集。这实际上是在为介绍jQuery的链式编程做准备。
jQuery的链式编程能力不但允许以简洁的方式写出强大的操作,而且提高了效率,因为它能够把多个命令应用到包装集中,而不必重新计算包装集。
在使用jQuery编写链式命令时,有两个重要的方法:end()
和andSelf()
。
方法 | 参数 | 返回值 | 描述 |
end() | 无 | 前一个包装集 | 在jQuery的命令链中使用,可以返回到前一个包装集。 |
andSelf() | 无 | 合并后的包装集 | 合并命令链中最近产生的两个包装集 |
来看下面的一个例子,这个例子中对一个表格进行clone()
复制操作。通过这个例子来研究jQuery的链式编程。
这个例子使用的HTML代码如下:
<div id="table1" class="table-responsive"> <table id="table-2" class="table table-bordered table-striped"> <thead> <tr> <td>#</td> <td>名字</td> <td>性别</td> <td>年龄</td> </tr> </thead> <tbody> <tr> <td>1</td> <td>张晓亮</td> <td>男</td> <td>26</td> </tr> ....... </tbody> </table> </div> <div id="table2" class="table-responsive"> <table id="table-2" class="table table-bordered table-striped"> <thead> <tr> <td>#</td> <td>名字</td> <td>性别</td> <td>年龄</td> </tr> </thead> </table> </div>
现在得到的效果如下图所示:
接下来我们使用复制命令,将表格1的内容复制给表格2。
$("#table-1 tbody").clone().appendTo("#table-2");
现在我们得到了2个表格。由于clone()
和appendTo()
命令得到的都是新的包装集,所以如果我们接着在上面的命令链上执行操作只会影响到新的表格(#table2
)。例如:
$("#table-1 tbody").clone().appendTo("#table-2") .find("tr:nth-child(even)") .addClass("success");
结果如下图所示,注意上面使用的是find()
方法,而不是filter()
方法。结果只有第二个表格的偶数行会变为绿色。
如果想在执行appendTo()
方法之后再操作原来的#table1
表格,我们就需要使用2次end()
方法才能返回到原始的包装集,例如:
$("#table-1 tbody").clone().appendTo("#table-2") .end().end().find("tr:nth-child(even)") .addClass("success");
上面的小例子展示了end()
的使用方法。
对于andSelf()
方法,它用于合并命令链中最近产生的两个包装集。还是以上面的表格作为例子,在执行复制之后,我们希望将两个表格的偶数行都变为绿色,可以执行下面的代码:
$("#table-1 tbody").clone().appendTo("#table-2") .end().andSelf().find("tr:nth-child(even)") .addClass("success");
第一个end()
方法返回被克隆表格的包装集,然后通过andSelf()
方法将克隆表格包装集和原始包装集进行合并,再从中查找偶数行的tr
原始,将它们的颜色变成绿色。
小结
这篇文章中介绍了jQuery包装集的内容。理解jQuery的包装集是使用jQuery的基础。研究包装集一定要弄明白各个包装集方法会返回什么结果,我们总结如下:
返回原包装集的方法有:
size()
get
add()
not()
filter()
返回新包装集的方法有:
slice()
find()
clone()
children()
contents()
next()
nextAll()
parent()
parents()
prev()
prevAll()
siblings()
appendTo()
prependTo()
insertBefore()
insertAfter()
replaceAll()
add()
会添加新的元素到包装集,filter()
和not()
方法是在当前包装集的基础上进行过滤和取消(特别注意不是在包装集中进行过滤)。
slice()
,is()
方法都和not()
方法类似。
find()
,parent()
,children()
等方法是在当前包装集的元素中去查找或过滤,而不是在包装集中过滤。
要清楚的明白每一个方法会返回什么包装集,这样在我们进行链式编程的时候才会得心应手,不会出现莫名其妙的错误。