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

Yet another closest child thread: finding the nearest ancestor of an element that matches a selector

本文关键字:元素 最近 祖先 选择器 查找 最接近 线程 另一个      更新时间:2023-09-26

下面是一个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,不包括属于嵌套模块的模块。

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

例如,我可以这样做:

$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() .

你可以过滤父母

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

这排除了任何.module-bar嵌套的 depper 而不是一个.module

小提琴

或者(内部与上述相同,因此可能不会更有效率(

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

小提琴

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

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

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

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

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

但我假设.module-bar将在主要.module下,而.modules的孩子将在主要.module下。

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