jQuery:find() 子项,直到遇到某个阈值元素



我有一个嵌套的表结构,如下所示

<table>
<td id="first">
<div class="wrapper">
<input name=1>
</div>
<input name=2>
<table>
<td id="second">
<input name=3>

我有 j查询选择$("#first").我想遍历并find()在这个<td>上下文中<input>s的所有孩子,但不要下降到嵌套的<table>s。

所以我需要一个jQuery技巧

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

  • 将在 DOM 树中下降 n 级

  • 但如果遇到某个元素(<table>)将停止降序,因此选择器不会选择嵌套表的输入(将单独处理)

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

我检查了其他jQuery查找,直到问题。他们有答案,但似乎他们不符合最后一个标准

我在另一个问题中遇到了类似的问题。在与一些人来回尝试寻找选择器之后,我最终终于自己想出了一个插件。

用法 :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;
}

更新:让我们再来一次。

基本上,您希望匹配所有<input>元素,这些元素是#first的后代,并且不是嵌套在#first下多个级别的<td>元素的子元素。

(我不确定最后under #first部分,但实现它允许我们支持祖先链中#first以上的<td>元素。

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

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

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

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

原答案如下:

您可以使用 not() 排除具有多个<td>祖先的<input>元素:

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

嗯,我有一个更好的主意。

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

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

如果速度很慢,只需手动为您的算法编写代码即可。没有选择器快捷方式。

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

对函数使用速记 lambda 表示法(正如您可以在打字稿中编写的那样),这将导致:

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

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

这是一个快速干净的实用程序函数,可以完成您正在寻找的操作:

// finds the selector, but excludes any matches found under the mask
$.fn.findExclude = function(selector, mask) {
return this.find(selector).not(this.find(mask).find(selector))
}

在您的情况下,您可以这样称呼它:

$("#first").findExclude("input", "table")

这将找到任何input元素,但不包括那些作为table后代找到的元素。

堆栈代码段中的演示

// finds the selector, but excludes any matches found under the mask
$.fn.findExclude = function(selector, mask) {
return this.find(selector).not(this.find(mask).find(selector))
}
$("#first").findExclude("input", "table").css({background:"red"})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<td id="first">
<div class="wrapper">
<input value=1 />
</div>
<input value=2>
<table>
<td id="second">
<input value=3 />
</td>
</table>
</td>
</table>

延伸阅读

  • 跳过 jQuery.find() 中的递归以获得选择器?
  • jQuery find() until?
  • 是否可以阻止 jQuery.find() 在 DOM 树的某些节点下搜索?

相关内容

最新更新