【问题标题】:jQuery find first level elements with a class but not nested elements insidejQuery找到具有类但没有嵌套元素的第一级元素
【发布时间】:2021-06-06 01:26:25
【问题描述】:

这是示例 HTML(id 将不存在,此处添加用于演示目的)

<div id="root" class="node">
    <div class="[any class that is not `node`]">
        <div class="[any class that is not `node`]">
            <div class="node" id="n0"></div>
        </div>
        <div class="node" id="n1"></div>
        <div class="node" id="n2"></div>
        <div class="node" id="n3"></div>
        <div class="node" id="n4">
            <div class="[any class that is not `node`]">
                <div class="node" id="n4_1"></div>
            </div>
            <div class="[any class that is not `node`]">
                <div class="node" id="n4_2"></div>
            </div>
        </div>
    </div>
    <div class="node" id="n5"></div>
    <div class="node" id="n6"></div>
    <div class="node" id="n7"></div>
    <div class="node" id="n8">
        <div class="[any class that is not `node`]">
            <div class="node" id="n8_1"></div>
        </div>
        <div class="[any class that is not `node`]">
            <div class="node" id="n8_2"></div>
        </div>
    </div>
</div>

使用函数在根中查找第一级节点:

function findNextLevelNodes($elem) {
    // example code
    let selector = '[selector to include next nodes, but not nodes nested within those]';
    $elem.find(selector).each((i, node) => console.log($(node).attr('id')));
}

这样

let $root = $('#root');
findNextLevelNodes($root);
// should print n0, n1, n2, n3, n4, n5, n6, n7, n8
// should not print n4_1, n4_2, n8_1, n8_2

看起来很简单,但我找不到可以得到这个结果的选择器。

发现了类似的问题,但对答案不满意,当然这应该很容易做到,无需手动循环遍历所有孩子

类似的问题 -

jQuery find only not nested elements

  • 这有一个解决方案,它依赖于循环遍历#root 中的所有元素
  • node 可以嵌套到任何级别,所以如果我不必递归循环遍历 #root 中的每个元素,我会更喜欢

Selecting first instance of class but not nested instances via jQuery

  • 答案取决于 html 的非节点元素的类/标签,因此不适用

编辑

findNextLevelNodes 在我的情况下需要高效,因为它将为每个子节点递归调用,如果findNextLevelNodes 本身具有递归所有子节点,或者.parents 调用,我有一种感觉可能不是对大型 node 树进行高效处理

现在看来,我必须更改 html 类以保持效率,有点像

<div id="root" class="node l0">
    <div class="[any class that is not `node`]">
        <div class="[any class that is not `node`]">
            <div class="node l1" id="n0"></div>
        </div>
        <div class="node l1" id="n1"></div>
        <div class="node l1" id="n2"></div>
        <div class="node l1" id="n3"></div>
        <div class="node l1" id="n4">
            <div class="[any class that is not `node`]">
                <div class="node l2" id="n4_1"></div>
            </div>
            <div class="[any class that is not `node`]">
                <div class="node l2" id="n4_2"></div>
            </div>
        </div>
    </div>
    <div class="node l1" id="n5"></div>
    <div class="node l1" id="n6"></div>
    <div class="node l1" id="n7"></div>
    <div class="node l1" id="n8">
        <div class="[any class that is not `node`]">
            <div class="node l2" id="n8_1"></div>
        </div>
        <div class="[any class that is not `node`]">
            <div class="node l2" id="n8_2"></div>
        </div>
    </div>
</div>

// now this should work
function findNextLevelNodes($root, level) {
    return $root.find('.node.l' + level);
}

看起来有点hacky,我会等待一段时间,看看我是否找到了更优雅和更高效的东西,否则将不得不这样做。

【问题讨论】:

    标签: javascript html jquery jquery-selectors


    【解决方案1】:

    您可以通过使用recursive 函数来实现这一点 这是函数

    function findNextLevelNodesByClass($elem, className) {
    
      let nodesArray = [];
      
      function getRecursiveNextDom($rootNode) {
        $rootNode.children().each((i, elemnt) => {
          if ($(elemnt).hasClass(className))
            nodesArray.push(elemnt)
          else
            getRecursiveNextDom($(elemnt));
        })
      }
      
      
      getRecursiveNextDom($elem,className);
      
      return nodesArray;
    }
    

    查看工作 sn-p :

    function findNextLevelNodesByClass($elem, className) {
    
      let nodesArray = [];
      
      function getRecursiveNextDom($rootNode) {
        $rootNode.children().each((i, elemnt) => {
          if ($(elemnt).hasClass(className))
            nodesArray.push(elemnt)
          else
            getRecursiveNextDom($(elemnt));
        })
      }
      
      
      getRecursiveNextDom($elem,className);
      
      return nodesArray;
    }
    
    
    let $root = $('#root');
    let result = findNextLevelNodesByClass($root, 'node');
    //result.forEach( element => console.log(element.id))
    console.log( result.map(function(y){return y.id}).join(','))
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="root" class="node">
      <div class="anyclass">
        <div class="anyclass">
          <div class="node" id="n0"></div>
        </div>
        <div class="node" id="n1"></div>
        <div class="node" id="n2"></div>
        <div class="node" id="n3"></div>
        <div class="node" id="n4">
          <div class="anyclass">
            <div class="node" id="n4_1"></div>
          </div>
          <div class="anyclass">
            <div class="node" id="n4_2"></div>
          </div>
        </div>
      </div>
      <div class="node" id="n5"></div>
      <div class="node" id="n6"></div>
      <div class="node" id="n7"></div>
      <div class="node" id="n8">
        <div class="anyclass">
          <div class="node" id="n8_1"></div>
        </div>
        <div class="anyclass">
          <div class="node" id="n8_2"></div>
        </div>
      </div>
    </div>

    【讨论】:

    • 编辑了我对使用递归调用的担忧,因为findNextLevelNodes 本身打算递归使用,我会四处寻找更好的解决方案,似乎没有就像有更好的解决方案一样
    • okey ,使用此解决方案,您无需添加额外的级别,无论是否为深节点级别,它都适用于所有情况:)
    【解决方案2】:

    我没有看到其他解决方案:从所有 .node 中,我正在过滤只有 1 个父级 .node.node(至少是 root)

    $('#root .node').filter( (s,e) => $(e).parents(".node").length < 2); // or length == 1
    

    我写了 root 有一个类节点,否则设置

    你也可以写:

    $('#root').find(".node").filter( (s,e) => $(e).parents(".node").length < 2);
    

    $('.node').filter( (s,e) => $(e).parents(".node").length == 1);
    

    如果添加指示级别的类,

    $("#root .node.l1") 会给你结果..而且效率更高

    【讨论】:

    • 编辑了我对使用.parents 呼叫的担忧,我会四处寻找更好的解决方案,但似乎没有更好的解决方案,谢谢帮助
    • 如果搜索 html 对你来说是一个重要的元素,我建议你在这个意义上构建你的 html.. 例如创建具有内部级别的 id..
    猜你喜欢
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-11
    • 1970-01-01
    • 2011-11-19
    • 2014-02-12
    相关资源
    最近更新 更多