JQuery - 查找任何级别的所有后代,但不查找这些后代的后代



QUESTION:

我正在尝试使用 JQuery 的.find()来查找任何级别的元素中具有给定属性的所有后代,而不是具有相同属性的那些后代的后代。

为了帮助理解:

杰奎里

以下查询的预期目标是查找元素$("#some_id")(在任何级别(中具有some_attribute属性的所有后代,但不查找具有相同属性的这些后代的后代。

$("#some_id").find("[some_attribute]");

.HTML

<span id="some_id" some_attribute>
<span some_attribute> <!-- SELECT -->
<span some_attribute> <!-- IGNORE -->
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span>
</span>
</span>
<span>
<span some_attribute> <!-- SELECT -->
<span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
</span>
<span>
<span>
<span>
<span some_attribute> <!-- SELECT -->
</span>
</span>
</span>
</span>
</span>

注意:我需要一个通用方法...我解释得更好!假设我不知道选择器$("#some_id")我只有该查询的结果。还要考虑到此结果可能引用可能位于具有some_attribute属性的另一个元素中的元素。

您可以使用:not来确保所选元素与特定选择器不匹配 - 在这里,#some_id [some_attribute] [some_attribute](因为与该选择器匹配的元素将是嵌套在另一个不是#some_idsome_attribute中的some_attribute(:

const result = $("#some_id")
.find("[some_attribute]:not(#some_id [some_attribute] [some_attribute])")
.each(function() {
console.log(this.innerHTML);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="some_id" some_attribute>
<span some_attribute>sel <!-- SELECT -->
<span some_attribute> <!-- IGNORE -->
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span>
</span>
</span>
<span>
<span some_attribute>sel <!-- SELECT -->
<span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
</span>
<span>
<span>
<span>
<span some_attribute>sel <!-- SELECT -->
</span>
</span>
</span>
</span>
</span>

如果您无法对其进行硬编码,我想一个选项是设置一个属性,以便您可以正确使用:not

const elm = $("#some_id");
elm[0].dataset.parent = '';
elm
.find("[some_attribute]:not([data-parent] [some_attribute] [some_attribute])")
.each(function() {
console.log(this.innerHTML);
});
elm[0].removeAttribute('data-parent');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="some_id" some_attribute>
<span some_attribute>sel <!-- SELECT -->
<span some_attribute> <!-- IGNORE -->
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span>
</span>
</span>
<span>
<span some_attribute>sel <!-- SELECT -->
<span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
</span>
<span>
<span>
<span>
<span some_attribute>sel <!-- SELECT -->
</span>
</span>
</span>
</span>
</span>

如果您也不想更改 DOM,请.filter并检查带有[some_attribute].closest元素是否为父元素:

const elm = $("#some_id");
elm
.find("[some_attribute]")
.filter(function() {
return $(this).parent().closest('[some_attribute]')[0] === elm[0];
})
.each(function() {
console.log(this.innerHTML);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="some_id" some_attribute>
<span some_attribute>sel <!-- SELECT -->
<span some_attribute> <!-- IGNORE -->
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span>
</span>
</span>
<span>
<span some_attribute>sel <!-- SELECT -->
<span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
</span>
<span>
<span>
<span>
<span some_attribute>sel <!-- SELECT -->
</span>
</span>
</span>
</span>
</span>

使用旧版本的jQuery,您可以使用.selector

const elm = $("#some_id");
const sel = elm.selector;
elm
.find(`[some_attribute]:not(${sel} [some_attribute] [some_attribute])`)
.each(function() {
console.log(this.innerHTML);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<span id="some_id" some_attribute>
<span some_attribute>sel <!-- SELECT -->
<span some_attribute> <!-- IGNORE -->
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span>
</span>
</span>
<span>
<span some_attribute>sel <!-- SELECT -->
<span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
<span some_attribute> <!-- IGNORE -->
</span>
</span>
</span>
<span>
<span>
<span>
<span some_attribute>sel <!-- SELECT -->
</span>
</span>
</span>
</span>
</span>

这是我的解决方案。有关更多说明,请参阅下面的代码说明...

// NOTE: Find all descendants at any level, but not the descendants of those descendants.
// By Questor
function findDescsNotDescsOfThose(jqPntElOrPntQry, jqFind){
var jqElInst;
if (typeof jqPntElOrPntQry === "string" || 
jqPntElOrPntQry instanceof String) {
// [Ref.: https://stackoverflow.com/a/9436948/3223785 ]
jqElInst = $(jqPntElOrPntQry);
} else {
jqElInst = jqPntElOrPntQry;
}
return jqElInst.find(jqFind)
.filter(function(){
// NOTE: We need use ".parent ()" and then ".closest ()", otherwise ".closest ()"
// will find the element itself if it fits "jqFind". By Questor
descOfjqFind = $(this).parent().closest(jqFind);
// NOTE: Checks if it is not descended from any element that also fits
// in "jqFind". Being descended from an element that also fits "jqFind"
// checks to see if this element is descended from "jqElInst". By Questor
if (descOfjqFind.length > 0 && $(descOfjqFind).
parent().closest(jqElInst).length === 1) {
return false
}
return true;
});
}

谢谢!=D

最新更新