jQuery之end()和pushStack()

jQuery链式调用技巧
本文深入探讨jQuery的pushStack()和end()方法,解析如何优化DOM遍历插件,实现更灵活的链式调用,提升代码效率。

原文: https://www.cnblogs.com/AndyWithPassion/archive/2012/02/06/jquery_pushStack_javascript.html

jquery.fn.end()方法, pushStack()

jQuery之end()和pushStack()

 

pushStack()方法在jQuery的DOM操作中被频繁的使用, 如在parent(), find(), filter()中, 当然还有其他许多类似的方法, 它们往往需要返回一个jQuery封装过的DOM结果集.但在我们自己写jQuery代码的时候,却很少关注或使用过pushStack(). 如果我们需要写个涉及DOM遍历的插件,它就会显得尤其有用.

在jQuery内部,pushStack()方法通过改变一个jQuery对象的prevObject属性来"跟踪"链式调用中前一个方法返回的DOM结果集(被jQuery封装过,也是个jQuery对象,说是"跟踪",是因为实际存储的是个引用). 当我们再链式调用end()方法后, 内部就返回当前jQuery对象的prevObject. 具体更多细节, 直接看源码即可. 这里只做个简单的分析, 直接来个例子:

html:

复制代码
 1 <div id="grandparent">
 2     I am grandparent.
 3     <div id="parent">
 4         I am parent.
 5         <div id="child">
 6             I am child.
 7         </div>
 8     </div>
 9 </div>
10         
复制代码

javascript:

1 var els = $('#child').parent().parent();
2 console.dir(els);

图解:

了解这个之后, 我们来做一个grandparent插件,用来替代.parent().parent()这样连续2次的调用,直接用.grandparent().如果"一不小心"没考虑end()的话,代码很可能就是这个样子的:

$.fn.grandparent = function () {
     return  this .parent().parent();
};

依旧用上面那个例子:

1
$( '#child' ).grandparent().end();  //jQuery-[div#parent]

很显然, 大多数情况下这不是我们想要的, 事实上我们想通过链式调用end()直接返回到jquery[div#child]. 现在该是pushStack出马的时候了,我们只要加上一行即可:

1
2
3
4
$.fn.grandparent =  function () {
     var  els =  this .parent().parent();
     return  this .pushStack(els.get());
};

在pushStack内部, 把els.get()返回的DOM数组封装成一个新的jQuery对象, 而this(jQuery[div#child])会赋值给之前新构建jQuery的prevObject, 最后返回新生的那个jQuery对象.

所以这次, 当我们再用end()就对了:

var  grandparent = $( '#child' ).grandparent(). /* jquery-[div#grandparent]*/ .end() /*jquery-[div#child]*/

此博文内容的主体思想来自Learning JQuery中的一篇博客, 感谢该作者的分享. 感兴趣的话, 点击jQuery pushStack.

------------------------------------------------------------------------------------------------------------

end() 方法结束当前链条中的最近的筛选操作,并将匹配元素集还原为之前的状态。

语法

.end()

详细说明

大多数 jQuery 的遍历方法会操作一个 jQuery 对象实例,并生成一个匹配不同 DOM 元素集的新对象。当发生这种情况时,应该会把新的元素集推入维持在对象中的堆栈内。每次成功的筛选方法调用都会把新元素推入堆栈中。如果我们需要老的元素集,可以使用 end() 从堆栈中弹出新集合。

假设页面中有一对很短的列表:

<ul class="first">
   <li class="foo">list item 1</li>
   <li>list item 2</li>
   <li class="bar">list item 3</li>
</ul>
<ul class="second">
   <li class="foo">list item 1</li>
   <li>list item 2</li>
   <li class="bar">list item 3</li>
</ul>

例子 1

主要是在利用 jQuery 的链条属性(命令链)时,jQuery 会比较有用。如果不使用命令链,我们一般是通过变量名来调用之前的对象,这样我们就不需要操作堆栈了。不过通过 end(),我们可以把所有方法调用串联在一起:

$('ul.first').find('.foo').css('background-color', 'red')
  .end().find('.bar').css('background-color', 'green');

亲自试一试

这条命令链检索第一个列表中类名为 foo 的项目,并把它们的背景设置为红色。end() 会将对象还原为调用 find() 之前的状态,所以第二个 find() 查找的是 <ul class="first"> 内的 '.bar' ,而不是在列表的 <li class="foo"> 中查找,并将匹配元素的背景设置为绿色。最后的结果是第一个列表中的项目 1 和项目 3 被设置了带颜色的背景,而第二个列表中的项目没有任何变化。

例子 2

这条长长的 jQuery 链可以可视化为结构化的代码块,筛选方法打开嵌套代码块,而 end() 方法用来关闭代码块:

$('ul.first').find('.foo')
  .css('background-color', 'red')
.end().find('.bar')
  .css('background-color', 'green')
.end();

亲自试一试

最后这个 end() 不是必需的,因为我们随后会丢弃这个 jQuery 对象。不过,如果按照这种形式编写代码,end() 就能提供视觉上的对称,以及规整程序的感觉,至少对于开发者来说更易阅读,当然代价则是由于进行了额外的调用,会有一点点性能损失。

------------------------------------------------------------------------------

转载于:https://www.cnblogs.com/oxspirt/p/10780436.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值