Gar*_*orn 6 javascript recursion jquery traversal jquery-traversing
TL; DR:我如何得到像find()这样的动作,但阻止某个选择器的遍历(不是完全停止,只是跳过)?
解答: $(Any).find(Selector).not( $(Any).find(Mask).find(Selector) )
有许多真正伟大的答案,我希望我可以更多地分配赏金点数,也许我应该为这些中的一些做出50 pt奖励; p我选择Karl- AndréGagnon 's因为这个答案设法让findExclude不需要一条,稍长,一条线.虽然这使用了三个查找调用和一个重度不过滤器,但在大多数情况下,jQuery可以使用非常快速的实现来跳过大多数find()的遍历.
下面列出了特别好的答案:
falsarella:我的解决方案有很好的改进,findExclude(),在许多情况下都是最好的
Zbyszek:一种类似于falsarella的基于过滤器的解决方案,在效率方面也很出色
贾斯汀:一个完全不同但可管理和功能性的解决方案来解决问题
每一种都有其独特的优点,值得一提.
我需要完全下降到一个元素并比较选择器,将所有匹配的选择器作为数组返回,但是当遇到另一个选择器时跳过下降到树中.
编辑:用我网站上的一些替换原始代码示例
这是一个消息论坛,可能有回复消息组嵌套在任何消息中.
但请注意,我们不能使用消息或内容类,因为该脚本也用于论坛之外的其他组件.只InterfaceGroup,Interface和controls类是潜在有用的-并且优选地只是接口和控制.
与代码交互并在JS Fiddle中查看它,感谢Dave A,这里在查看JavaScript控制台时单击按钮,可以看到控件类每个级别的.Interface嵌套被绑定一个额外的时间.
Visual A,论坛布局结构:
<li class="InterfaceGroup">
<ul class="Interface Message" data-role="MessagePost" >
<li class="instance"> ... condensed ... </li>
<li class="InterfaceGroup"> ... condensed ...</li>
</ul>
<ul class="Interface Message" data-role="MessagePost" >
<li class="instance"> ... condensed ... </li>
</ul>
<ul class="Interface Message" data-role="MessagePost" >
<li class="instance"> ... condensed ... </li>
<li class="InterfaceGroup"> ... condensed ...</li>
</ul>
</li>
Run Code Online (Sandbox Code Playgroud)
在每个内部<li class="InterfaceGroup">可以有相同结构的任意数量的重复(每个组是消息的线程)和/或更深的嵌套,例如..
<li class="InterfaceGroup">
<ul class="Interface Message" data-role="MessagePost" >
<li class="instance"> ... condensed ... </li>
<li class="InterfaceGroup">
<ul class="Interface Message" data-role="MessagePost" >
<li class="instance"> ... condensed ... </li>
<li class="InterfaceGroup"> ... condensed ...</li>
</ul>
</li>
</ul>
</li>
Run Code Online (Sandbox Code Playgroud)
在每个内部都有可以出现<li class="instance"> ... </li>的另一个团队决定的任意位置,class="controls"并且应该绑定一个事件监听器.虽然这些包含消息,但是其他组件任意构造它们的标记,但是总是有.controls内部的.Interface,它们被收集到.InterfaceGroup.内部内容(对于论坛帖子)的复杂度降低的版本在下面以供参考.
Visual B,带控件类的消息内容:
<ul class="Interface Message" data-role="MessagePost" >
<li class="instance">
<ul class="profile"> ...condensed, nothing clickable...</ul>
<ul class="contents">
<li class="heading"><h3>Hi there!</h3></li>
<li class="body"><article>TEST Message here</article></li>
<li class="vote controls">
<button class="up" data-role="VoteUp" ><i class="fa fa-caret-up"> </i><br/>1</button>
<button class="down" data-role="VoteDown" >0<br/><i class="fa fa-caret-down"> </i></button>
</li>
<li class="social controls">
<button class="reply-btn" data-role="ReplyButton" >Reply</button>
</li>
</ul>
</li>
<li class="InterfaceGroup" > <!-- NESTING OCCURRED -->
<ul class="Interface Message" data-role="MessagePost" >
<li class="instance">... condensed ... </li>
<li class="InterfaceGroup" >... condensed ... </li>
</ul>
</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
我们只能结合是控制接口类中,instance可能会或可能不存在,但界面.事件冒泡到.controls元素并且具有对.Interface它们的引用..
所以我想 $('.Interface').each( bind to any .controls not inside a deeper .Interface )
这是棘手的部分,因为
.Interface .controls将.control在.each()中多次选择相同的我怎么能用jQuery.find()或类似的jQuery方法呢?
我一直在考虑,也许,使用没有选择器的孩子可以工作,并且可以做同样的事情,如发现在引擎盖下,但我不太确定它实际上是或不会导致可怕的性能.仍然,一个有效的答案可以接受.儿童.
更新:最初我尝试使用伪造的例子来简洁,但希望看到一个论坛结构将有助于澄清问题,因为它们是自然嵌套的结构.下面我也发布部分javascript供参考,第二行的init函数是最重要的.
减少JavaScript部分:
var Interface=function()
{
$elf=this;
$elf.call=
{
init:function(Markup)
{
$elf.Interface = Markup;
$elf.Controls = $(Markup).find('.controls').not('.Interface .controls');
$elf.Controls.on('click mouseenter mouseleave', function(event){ $elf.call.events(event); });
return $elf;
},
events:function(e)
{
var classlist = e.target.className.split(/\s+/), c=0, L=0;
var role = $(e.target).data('role');
if(e.type == 'click')
{
CurrentControl=$(e.target).closest('[data-role]')[0];
role = $(CurrentControl).data('role');
switch(role)
{
case 'ReplyButton':console.log('Reply clicked'); break;
case 'VoteUp':console.log('Up vote clicked'); break;
case 'VoteDown':console.log('Down vote clicked'); break;
default: break;
}
}
}
}
};
$(document).ready( function()
{
$('.Interface').each(function(instance, Markup)
{
Markup.Interface=new Interface().call.init(Markup);
});
} );
Run Code Online (Sandbox Code Playgroud)
如果要在find中排除元素,可以使用非过滤器.例如,我已经采取了排除元素的功能,并使其更短:
$.fn.findExclude = function( Selector, Mask,){
return this.find(Selector).not(this.find(Mask).find(Selector))
}
Run Code Online (Sandbox Code Playgroud)
现在,对你说实话,我并不完全明白你想要什么.但是,当我看看你的功能时,我看到了你想要做的事情.
无论如何,看看这个小提琴,结果与你的相同:http://jsfiddle.net/KX65p/8/
| 归档时间: |
|
| 查看次数: |
2718 次 |
| 最近记录: |