【问题标题】:JavaScript: How to get parent element by selector?JavaScript:如何通过选择器获取父元素?
【发布时间】:2012-12-23 11:04:24
【问题描述】:

例子:

<div someAttr="parentDiv. We need to get it from child.">
    <table>
        ...
        <td> <div id="myDiv"></div> </td>
        ...
    </table>
</div>

我想通过一些选择器从内部 div 元素(具有myDiv 类的那个)中获取父级。

我如何使用纯 JavaScript不使用 jQuery 实现这一点?

类似:

var div = document.getElementById('myDiv');
div.someParentFindMethod('some selector');

【问题讨论】:

标签: javascript dom


【解决方案1】:

您可以在现代浏览器中使用closest()

var div = document.querySelector('div#myDiv');
div.closest('div[someAtrr]');

使用对象检测来提供polyfill 或替代方法以实现与 IE 的向后兼容性。

【讨论】:

【解决方案2】:

这是最基本的版本:

function collectionHas(a, b) { //helper function (see below)
    for(var i = 0, len = a.length; i < len; i ++) {
        if(a[i] == b) return true;
    }
    return false;
}
function findParentBySelector(elm, selector) {
    var all = document.querySelectorAll(selector);
    var cur = elm.parentNode;
    while(cur && !collectionHas(all, cur)) { //keep going up until you find a match
        cur = cur.parentNode; //go up
    }
    return cur; //will return null if not found
}

var yourElm = document.getElementById("yourElm"); //div in your original code
var selector = ".yes";
var parent = findParentBySelector(yourElm, selector);

【讨论】:

  • 这是相当低效的,因为它在整个文档中使用该选择器检索所有元素,而不仅仅是检查父元素。
  • 这个JSPerf test 分析了Element.matches()Element.closest(),以及每种方法的一个polyfill。 Element.matches() 的 polyfill 看起来与您的实现非常相似。为了解决@user663031 的性能问题,也许您可​​以使用Element.matches() 而不是Document.querySelectorAll()。它似乎比相关的 polyfill 运行得更快。
  • 同意user663031
【解决方案3】:

找到与给定选择器匹配的最近的父元素(或元素本身)。还包括一个停止搜索的选择器,以防您知道应该停止搜索的共同祖先。

function closest(el, selector, stopSelector) {
  var retval = null;
  while (el) {
    if (el.matches(selector)) {
      retval = el;
      break
    } else if (stopSelector && el.matches(stopSelector)) {
      break
    }
    el = el.parentElement;
  }
  return retval;
}

【讨论】:

  • closest 是个烂名字,应该命名为 "closestAncestor" ,如果最近的祖先是 10 个元素向上并且最近的后代是 1 个子元素,那么“最近的”将是后代,而不是祖先, 但是这个函数会返回祖先
【解决方案4】:

使用 leech 的答案和 indexOf(支持 IE)

这是使用 leech 所说的,但使其适用于 IE(IE 不支持匹配):

function closest(el, selector, stopSelector) {
  var retval = null;
  while (el) {
    if (el.className.indexOf(selector) > -1) {
      retval = el;
      break
    } else if (stopSelector && el.className.indexOf(stopSelector) > -1) {
      break
    }
    el = el.parentElement;
  }
  return retval;
}

它并不完美,但如果选择器足够独特,它就可以工作,这样它就不会意外匹配不正确的元素。

【讨论】:

    【解决方案5】:

    这是一个递归解决方案:

    function closest(el, selector, stopSelector) {
      if(!el || !el.parentElement) return null
      else if(stopSelector && el.parentElement.matches(stopSelector)) return null
      else if(el.parentElement.matches(selector)) return el.parentElement
      else return closest(el.parentElement, selector, stopSelector)
    }
    

    【讨论】:

      【解决方案6】:

      我想我会提供一个更健壮的示例,也可以使用 typescript,但转换为纯 javascript 会很容易。此函数将使用诸如“#my-element”之类的 ID 或类“.my-class”查询父母,并且与其中一些答案不同,它将处理多个类。我发现我命名了一些类似的东西,所以上面的例子找到了错误的东西。

      function queryParentElement(el:HTMLElement | null, selector:string) {
          let isIDSelector = selector.indexOf("#") === 0
          if (selector.indexOf('.') === 0 || selector.indexOf('#') === 0) {
              selector = selector.slice(1)
          }
          while (el) {
              if (isIDSelector) {
                  if (el.id === selector) {
                      return el
                  }
              }
              else if (el.classList.contains(selector)) {
                  return el;
              }
              el = el.parentElement;
          }
          return null;
      }
      

      按类名选择:

      let elementByClassName = queryParentElement(someElement,".my-class")

      按 ID 选择:

      let elementByID = queryParentElement(someElement,"#my-element")

      【讨论】:

        【解决方案7】:

        通过使用 querySelector()closest() 方法可以获得父元素。

        • querySelector() 返回与 a 匹配的第一个元素 文档中指定的 CSS 选择器。

        • closest() 在 DOM 树上搜索最近的元素 匹配指定的 CSS 选择器。

        使用示例

        var element = document.querySelector('td');
        console.log(element.closest('div'));
        <div>
          <table>
            <tr>
              <td></td>
            </tr>
          </table>
        </div>

        如果需要选择多个元素,querySelectorAll() 非常适合。

        • querySelectorAll() 将文档中与指定 CSS 选择器匹配的所有元素作为静态 NodeList 对象返回。

        要选择所需的元素,必须在[] 中指定它,例如第二个元素是:element[1]

        在以下示例中,closest() 方法用于获取特定选定元素的父 &lt;tr&gt; 元素。

        var element = document.querySelectorAll('td');
        console.log(element[1].closest('tr'));
        <div>
          <table>
            <tr id="1">
              <td> First text </td>
            </tr>
            <tr id="2">
              <td> Second text </td>
            </tr>
          </table>
        </div>

        【讨论】:

          【解决方案8】:

          函数 parent_by_selector 的简单示例,它返回父级或 null(没有选择器匹配):

          function parent_by_selector(node, selector, stop_selector = 'body') {
            var parent = node.parentNode;
            while (true) {
              if (parent.matches(stop_selector)) break;
              if (parent.matches(selector)) break;
              parent = parent.parentNode; // get upper parent and check again
            }
            if (parent.matches(stop_selector)) parent = null; // when parent is a tag 'body' -> parent not found
            return parent;
          };
          

          【讨论】:

            【解决方案9】:
            var base_element = document.getElementById('__EXAMPLE_ELEMENT__');
            for( var found_parent=base_element, i=100; found_parent.parentNode && !(found_parent=found_parent.parentNode).classList.contains('__CLASS_NAME__') && i>0; i-- );
            console.log( found_parent );
            

            【讨论】:

              【解决方案10】:

              这是访问父 ID 的简单方法

              document.getElementById("child1").parentNode;
              

              会魔法让你访问父 div。

              <html>
              <head>
              </head>
              <body id="body">
              <script>
              function alertAncestorsUntilID() {
              var a = document.getElementById("child").parentNode;
              alert(a.id);
              }
              </script>
              <div id="master">
              Master
              <div id="child">Child</div>
              </div>
              <script>
              alertAncestorsUntilID();
              </script>
              </body>
              </html>
              

              【讨论】:

              • 他希望父母有一些班级,而不仅仅是父母。
              • @torazaburo 这是来自 OP 的问题“JavaScript:如何通过选择器获取父元素?”它没有提到类
              • 选择器也可以是类或属性等
              猜你喜欢
              • 2023-04-08
              • 1970-01-01
              • 2018-03-12
              • 2018-12-29
              • 2015-10-15
              • 2011-12-07
              • 2023-02-02
              • 2016-07-22
              • 2017-06-30
              相关资源
              最近更新 更多