跳过jQuery.find()中用于选择器的递归? [英] Skip recursion in jQuery.find() for a selector?

查看:96
本文介绍了跳过jQuery.find()中用于选择器的递归?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR:我如何获得类似于find()的操作,但是对某个选择器阻止遍历(不是全停,只是跳过)?

答案:$(Any).find(Selector).not( $(Any).find(Mask).find(Selector) )

ANSWERS: $(Any).find(Selector).not( $(Any).find(Mask).find(Selector) )

有很多非常好的答案,我希望我能更多地分配赏金,也许我应该对其中的一些做出50分的赏金;我选择

There were many truly great answers, I wish I could some how distribute the bounty points more, maybe I should make some 50 pt bounties in response to some of these ;p I choose Karl-André Gagnon's because this answer managed to make findExclude unrequired in one, slightly long, line. While this uses three find calls and a heavy not filter, in most situations jQuery can use very fast implementation that skips traversal for most find()s.

下面列出了特别好的答案:

Especially good answers are listed below:

falsarella :对

falsarella: Good improvement on my solution, findExclude(), best in many situatoins

Zbyszek :类似于falsarella的基于过滤器的解决方案,而且效率很高

Zbyszek: A filter-based solution similar to falsarella's, also good on efficiency

Justin :针对底层问题的完全不同但可管理且功能强大的解决方案

Justin: A completely different, but manageable and functional solution to the underlaying issues

每一个都有其独特的优点,值得一提.

Each of these have their own unique merits and and are deserving of some mention.

我需要完全下降到一个元素中并比较选择器,将所有匹配的选择器作为数组返回,但是当遇到另一个选择器时,跳过下降到树中.

I need to descend into an element fully and compare selectors, returning all matched selectors as an array, but skip descending into the tree when another selector is encountered.

用我网站上的某些示例替换原始代码示例

这是针对消息论坛的,该论坛可能具有嵌套在任何消息内的答复消息组.
但是请注意,我们不能使用消息或内容类,因为该脚本还用于论坛之外的其他组件.只有InterfaceGroupInterfacecontrols类是潜在有用的-最好只是接口和控件.

This is for a message forum which may have reply message-groups nested inside any message.
Notice, however, we cannot use the message or content classes because the script is also used for other components outside of the forum. Only InterfaceGroup, Interface and controls classes are potentially useful - and preferably just Interface and controls.

与代码交互并在JS Fiddle中查看,谢谢Dave A,在这里单击在查看JavaScript控制台的同时单击按钮,以查看控件类在每个级别的.Interface嵌套中都绑定了一个额外的时间.

Interact with the code and see it in JS Fiddle, thanks Dave A, here Click on the buttons while viewing a JavaScript console to see that the controls class is being bound to one extra time per level of .Interface nesting.

Visual A,论坛布局结构:

Visual A, Forum Layout Struture:

    <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>

在每个<li class="InterfaceGroup">内部,可以有任意数量的相同结构重复项(每个组是一条消息线程)和/或更深层的嵌套,例如..

Inside of each <li class="InterfaceGroup"> there could be any number of repetitions of the same structure (each group is a thread of messages) and/or deeper nesting such as..

    <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>

在每个<li class="instance"> ... </li>中,都有另一个团队决定在其中出现class="controls"的任意位置,并且应绑定事件侦听器.尽管这些组件包含消息,但是其他组件可以任意构造其标记,但是在.Interface内部始终具有.controls,这些组件将被收集到.InterfaceGroup中.内部内容(针对论坛帖子)的简化后版本如下供参考.

Inside of each <li class="instance"> ... </li> there are arbitrary places decided by another team where class="controls" may appear and an event listener should be bound. Though these contain messages, other components structure their markup arbitrarily but will always have .controls inside of .Interface, which are collected into an .InterfaceGroup.A reduced-complexity version of the inner-content (for forum posts) is below for reference.

Visual B,带有控件类的消息内容:

Visual B, Message Contents with controls class:

<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>

我们只能绑定到Interface类中的 中的控件,instance可能存在或不存在,但Interface会存在. 事件冒泡到.controls元素,并引用了保存它们的.Interface..

We can only bind to controls that are within an Interface class, instance may or may not exist but Interface will. Events bubble to .controls elements and have a reference to the .Interface which holds them..

所以我正在尝试$('.Interface').each( bind to any .controls not inside a deeper .Interface )

那是棘手的部分,因为

  • .Interface .controls将在.each()
  • 中多次选择相同的.control
  • .not('.Interface .Interface .controls')取消任何更深层嵌套中的控件
  • .Interface .controls will select the same .control multiple times in the .each()
  • .not('.Interface .Interface .controls') cancels out controls in any deeper nesting

如何使用jQuery.find()或类似的jQuery方法来做到这一点?

How can I do this using jQuery.find() or a similar jQuery method for this?

我一直在考虑,也许使用带有非选择器的孩子可以工作,而可以可以做与幕后发现相同的事情,但是我不能确定它是否确实会导致可怕的性能.仍然可以有效地递归.children的答案.

I have been considering that, perhaps, using children with a not selector could work and could be doing the same thing as find under the hood, but I'm not so sure that it actually is or wont cause horrible performance. Still, an answer recursing .children effectively is acceptable.

更新:为简洁起见,起初我尝试使用psuedo示例,但希望看到论坛结构有助于澄清问题,因为它们是自然嵌套的结构.在下面,我还发布了部分javascript供参考,init函数的第二行最为重要.

精简的JavaScript部分:

Reduced JavaScript partial:

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);
    });
} );

推荐答案

如果要排除发现的元素,可以使用not过滤器.例如,我带您使用了不包含元素的函数,并使其变得更短:

If you want to exclude element in you find, you can use a not filter. As for example, I've taken you function that exclude element and made it way shorter :

$.fn.findExclude = function( Selector, Mask,){
    return this.find(Selector).not(this.find(Mask).find(Selector))
}

现在,对您不诚实,我还不完全了解您想要什么.但是,当我查看您的功能时,我看到了您要执行的操作.

Now, ill be honest with you, I did not fully understand what you want. But, when i took a look at your function, I saw what you were trying to do.

无论如何,看看这个小提琴,结果与您的相同: http://jsfiddle.net/KX65p/8 /

Anyway, take a look at this fiddle, the result is the same as your : http://jsfiddle.net/KX65p/8/

这篇关于跳过jQuery.find()中用于选择器的递归?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆