首页 > 解决方案 > JQuery - 查找任何级别的所有后代,但不是那些后代的后代

问题描述

问题:

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

帮助理解:

jQuery

下面查询的预期目标是查找元素$("#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属性的元素内。

标签: javascriptjqueryhtmldom

解决方案


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

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并检查.closest元素[some_attribute]是否是父元素:

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>


推荐阅读