【问题标题】:jQuery: find() children until a certain threshold element is encounteredjQuery:find()子元素,直到遇到某个阈值元素
【发布时间】:2016-10-05 12:49:44
【问题描述】:

我有一个类似的嵌套表结构

   <table>

       <td id="first">

           <div class="wrapper">
               <input name=1>
           </div>

           <input name=2>

           <table>

               <td id="second">

                   <input name=3>

我有 jQuery 选择 $("#first")。我想在这个&lt;td&gt; 上下文中遍历和find() 所有孩子&lt;input&gt;s,但不要下降到嵌套的&lt;table&gt;s。

所以我需要一个 jQuery 技巧

  • find()某个元素的所有子元素

  • 将在 DOM 树中向下下降 n 级

  • 但是如果遇到某个元素(&lt;table&gt;)就会停止下降,这样选择器就不会选择嵌套表的输入(将单独处理)

  • 可以有任意数量的嵌套&lt;table&gt; 级别,因此无论在$("#first")@ 范围内遇到多少父&lt;table&gt; 或子&lt;table&gt;,该解决方案都应该有效987654332@ 或任何其他&lt;td&gt;

我检查了其他 jQuery 查找直到问题。他们有答案,但似乎没有满足最后一个条件

【问题讨论】:

  • 你觉得你的表结构在这里好吗?
  • 结构是使用&lt;table&gt;还是其他一些元素自然与问题无关
  • 我问是因为您的input 标签格式不正确,还缺少tr
  • @freebird 我认为这只是一个匆忙拼凑的代码示例

标签: jquery


【解决方案1】:

我在this other question 中遇到了类似的问题。在与一些试图寻找查找选择器的人来来回回之后,我最终自己找出了一个插件。

用法: ExclusiveInputs = $('#first').findExclude('input','table');

// Find-like method which masks any descendant
// branches matching the Mask argument.
$.fn.findExclude = function( Selector, Mask, result){

    // Default result to an empty jQuery object if not provided
    var result = typeof result !== 'undefined' ?
                result :
                new jQuery();

    // Iterate through all children, except those match Mask
    this.children().each(function(){

        var thisObject = jQuery( this );
        if( thisObject.is( Selector ) ) 
            result.push( this );

        // Recursively seek children without Mask
        if( !thisObject.is( Mask ) )
            thisObject.findExclude( Selector, Mask, result );
    });

    return result;
}

(精简版)

$.fn.findExclude = function( selector, mask, result )
{
    var result = typeof result !== 'undefined' ? result : new jQuery();
    this.children().each( function(){
        var thisObject = jQuery( this );
        if( thisObject.is( selector ) ) 
            result.push( this );
        if( !thisObject.is( mask ) )
            thisObject.findExclude( selector, mask, result );
    });
    return result;
}

【讨论】:

    【解决方案2】:

    更新:让我们来看看这个。

    基本上,您希望匹配所有&lt;input&gt; 元素,这些元素是#first 的后代,并且不是&lt;td&gt; 元素的子元素,这些元素嵌套在#first 下一层以上。

    (我不确定最后的under #first 部分,但实现它可以让我们在祖先链中支持#first 以上的&lt;td&gt; 元素。)

    从技术上讲,仅以下选择器就可以满足您的要求:

    var inputs = $("#first td:not(#first td td) > input");
    

    如果这在您的浏览器中不起作用(我认为 Sizzle 应该可以胜任,但像 :not() 这样的复杂选择器总是很棘手),您可以将处理委托给 jQuery 方法:

    var inputs = $("#first td").not("#first td td").children("input");
    

    原答案如下:

    您可以使用not() 排除具有多个&lt;td&gt; 祖先的&lt;input&gt; 元素:

    var firstLevelCells = $("#first").find("input").not("td td input");
    

    【讨论】:

    • 我不明白;这不需要$("#first").find("input").not("td td input")吗?
    • 你说得对,我一直找不到要匹配的实际元素。答案已相应更新,感谢您的提醒:)
    【解决方案3】:

    嗯,我有个更好的主意..

    var badTable = "table.bad"; //the one you want to avoid
    var $goodInputs = $("#first").find('input').filter(function() {
        return $(this).closest(badTable).length == 0;
    });
    

    这可能对您来说足够快,也可能不够快。这取决于您不想谈论的 DOM ;)

    如果速度较慢,只需手动编写算法代码。没有选择器快捷方式。

    【讨论】:

    • 正如问题所说,您无法从上下文中识别出哪个表是“坏的”,但它必须适用于任何嵌套级别,无需特殊的类标记
    【解决方案4】:

    我遇到了类似的问题,并且仍然面临着在没有扩展循环或具有 DOM 的确切结构的情况下做某事的挑战。在我的例子中,我已经引用了元素“#first”,如果你不这样做,我们可以通过 each 来获取它(即使它只是一个对象)。诀窍是与 parentsuntil 一起回到树上并停在顶部元素处,看看是否有任何中间元素满足条件。

    使用函数的简写 lambda 表示法(你可以用打字稿写)这将导致:

    $('#first').each((idx, f) => $(f).find('input').filter((idx2, inp) => $(inp).parentsUntil(f, 'table').length == 0)
    

    这可能不是最有效的方式(因为您首先选择所有内容,然后通过再次安装 DOM 树来丢弃元素,但它是紧凑且相当通用的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-02
      • 1970-01-01
      • 2011-07-09
      • 1970-01-01
      • 1970-01-01
      • 2012-04-09
      • 1970-01-01
      • 2023-03-07
      相关资源
      最近更新 更多