另一个最接近的子线程:找到与选择器匹配的元素的最近祖先

时间:2014-04-16 16:12:24

标签: javascript jquery

以下是HTML模块的概述:

.module
  .module-title
  .module-foo
    .module-bar
  .module-children

模块可以相互嵌套:

.module
  .module-title
  .module-foo
    .module-bar
  .module-children
    .module
      .module-title
      .module-foo
        .module-bar
      .module-children
        .module
          .module-title
          .module-foo
            .module-bar
          .module-children
        .module
          .module-title
          .module-foo
            .module-bar
          .module-children
  .module
    .module-title
    .module-foo
      .module-bar
    .module-children

我已经将最顶层的.module存储在jQuery对象$module中。

现在,我想选择属于最顶层模块的.module-bar,不包括属于嵌套模块的模块。

问题在于我不想对层次结构进行硬编码

电子。 G。我能做到这一点:

$bar = $module.find('> .module-foo > .module-bar');

或者这个:

$bar = $module.find('.module-bar').eq(0);

但模块内容的结构会有细微的变化。子元素可能以不同的顺序出现,或以不同的方式嵌套。这些HTML更改中的任何一个都会破坏JS代码,我希望代码能够灵活且容忍HTML结构的微小变化。

相反,我想做类似的事情:

$bar = $module.closestChild('.module-bar');

我发现了一些问题和解决方案,可以全部描述为“反向closest()”。这是一个例子:https://github.com/jstnjns/jquery-nearest/但它不适合我,因为它只能阻止遍历目标实例。在我的情况下,目标元素不包含嵌套模块,因此nearest()将选择.module-bar的所有实例。

其他解决方案只是没有通过要求。例如,此https://stackoverflow.com/a/7051985/901944依赖于.first()

3 个答案:

答案 0 :(得分:2)

您可以过滤父母

var $bars = $module.find('.module-bar').filter(function() {
                return $(this).closest('.module').get(0) === $module.get(0);
            });

排除任何.module-bar嵌套的depper而不是.module

FIDDLE

或(内部与上述相同,因此效率可能不高)

 var $bars = $module.find('.module-bar').not('.module .module .module-bar');

FIDDLE

答案 1 :(得分:1)

所以我做了一个小的jQuery插件 jquery.closestchild ,它逐步遍历树,一旦找到匹配就不会再进一步​​了。

插件:https://github.com/lolmaus/jquery.closestchild/

演示:http://lolmaus.github.io/jquery.closestchild/

这是针对adeneo解决方案的性能测试:http://jsperf.com/closestchild#runner。该插件的执行速度提高了八倍,差异应该与DOM树深度成比例增长。

答案 2 :(得分:0)

$module.find(':not(.module .module .module-bar)').filter('.module-bar')

但我假设.module-bar位于主.module下,而子.modules位于主.module之下。

http://jsfiddle.net/zsQnH/2/