jQuery.closest()实现的DOM /纯JavaScript解决方案?

chr*_*lee 18 javascript dom

这是我正在尝试查询的标记.所以鉴于标记:

<table class="non-unique-identifier table">
<tr><td><div id="unique-identifier"></div></td></tr>
</table>
Run Code Online (Sandbox Code Playgroud)

我正在查询#unique-identifier:

var myDiv = document.getElementById('#unique-identifier');
Run Code Online (Sandbox Code Playgroud)

我正在尝试选择表格.问题是我想让代码不易碎,所以我不需要这样做:

var myDiv = document.getElementById('#unique-identifier'),
    myTable = myDiv.parentNode.parentNode.parentNode.parentNode;
Run Code Online (Sandbox Code Playgroud)

我的问题

目前是否存在jQuery等效于$().nearest()的DOM实现?没有嵌套for循环的最接近的实现将是优选的.

限制

我不需要为这个特定问题使用jQuery或sizzle或引入任何新库.代码也很老了.因此,这就是造成这种局限和存在的原因<tables>.

lea*_*eaf 33

没有循环就不能这样做:

function closest (el, predicate) {
  do if (predicate(el)) return el;
  while (el = el && el.parentNode);
}
Run Code Online (Sandbox Code Playgroud)

嗯,实际上你可以使用递归(一个伪装的循环):

function closest(el, predicate) {
  return predicate(el) ? el : (
     el && closest(el.parentNode, predicate)
  );
}
Run Code Online (Sandbox Code Playgroud)

一个演示(使用Sizzle进行DOM查询):

// s = selectors
// n = number of selectors
// get closest s[i+1] from s[i]
// where 0 <= i < n and i % 2 = 0

function main (s) {
  var i, el, from;
  var n = s.length;
  for (i = 0; i < n; i += 2) {
    from = Sizzle(s[i])[0];
    el = closest(from, function (el) {
      return !!el && el !== document && (
        Sizzle.matchesSelector(el, s[i + 1])
      );
    });
    console.log(el);
  }
}

function closest (el, predicate) {
  do if (predicate(el)) return el;
  while (el = el && el.parentNode);
}

main([
  "#winner" , "b", 
  "#winner" , "p", 
  "#winner" , "div", 
  "#winner" , "div:not(#trump)", 
  "#winner" , "#clinton",
  "#looser" , "html"
]);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/sizzle/1.10.18/sizzle.min.js"></script>

<div id="main">
  <div id="trump">
    <p>Donald <b id="winner">Trump</b></p>
  </div>
  <div id="clinton">
    <p>Hillary <b>Clinton</b></p>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)


Mic*_*l S 7

要添加更新的答案,现在Element.closest(<query_selector>)可用。

https://developer.mozilla.org/zh-CN/docs/Web/API/Element/closest

IE不支持此功能,但该mozilla doc页面包含用于IE8和IE9 +的polyfill的代码。

  • 尽管5年前当OP提出该要求时尚无此功能,但现在几乎所有的浏览器都可以使用本机解决方案(其余均使用标准的polyfill),但这绝对是任何实际实现的首选方法,尽管其他对于学术/教育目的,答案很有趣。 (2认同)

ant*_*xic 5

通过任何 css 选择器搜索最接近元素的简洁快速(使用 Benchmark.js 测试)方法:

var ep = Element.prototype;
ep.matches = ep.matches || ep.webkitMatchesSelector || ep.msMatchesSelector || ep.mozMatchesSelector;

function getClosest( elem, selector ) {
    while (elem !== document.body) {
        elem = elem.parentElement;
        if (elem.matches(selector)) return elem;
    }
}
Run Code Online (Sandbox Code Playgroud)

支持 IE9+ 和您可能关心的其他浏览器。