使用原生DOM的最近祖先匹配选择器?

hur*_*lad 15 javascript jquery standards w3c dom-traversal

是否有人在DOM api中处理jQuery.closest()等价物?

看起来选择器级别2草案添加matches()等效于jQuery.is(),因此本机最接近应该更容易编写.添加closest()选择器了吗?

Pau*_*ish 35

建立Alnitak的答案.这matchesSelector是当前matches在DOM规范中的工作当前实现.

// get nearest parent element matching selector
function closest(el, selector) {
    var matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;

    while (el) {
        if (matchesSelector.call(el, selector)) {
            break;
        }
        el = el.parentElement;
    }
    return el;
}
Run Code Online (Sandbox Code Playgroud)

浏览器支持非常棒:http://caniuse.com/matchesselector


小智 12

似乎Chrome 40将带来一个本地element.closest()方法(http://blog.chromium.org/2014/12/chrome-40-beta-powerful-offline-and.html),这里指定:https://dom.spec.whatwg .ORG /#DOM的元件最接近

  • `element.closest`已登陆Chrome 41,而不是40(参见https://crbug.com/422731#c7).它也登陆[Firefox 35](https://developer.mozilla.org/en-US/Firefox/Releases/35) (2认同)

Pav*_*o D 5

Element.closest()

它的支持

使用Element.matches()实现此类函数在性能方面似乎不是最佳的,因为看起来match()每次测试父级时都会调用querySelectorAll(),而只有一次调用就足够了.

这是MDN上最近()的polyfill.注意对querySelectorAll()的单个调用

if (window.Element && !Element.prototype.closest) {
  Element.prototype.closest = 
  function(s) {
      var matches = (this.document || this.ownerDocument).querySelectorAll(s),
          i,
          el = this;
      do {
          i = matches.length;
          while (--i >= 0 && matches.item(i) !== el) {};
      } while ((i < 0) && (el = el.parentElement)); 
      return el;
  };
}
Run Code Online (Sandbox Code Playgroud)

但请记住,像这样实现的函数将无法在未附加的树上正常工作(与document.documentElement根分离)

//Element.prototype.closestTest = function(s){...as seen above...};

var detachedRoot = document.createElement("footer");
var child = detachedRoot.appendChild(document.createElement("div"));
detachedRoot.parentElement; //null

child.closestTest("footer"); //null

document.documentElement.append(detachedRoot);
child.closestTest("footer"); //<footer>   
Run Code Online (Sandbox Code Playgroud)

虽然在Firefox 51.0.1中实现的nearest()似乎可以与分离树一起使用

document.documentElement.removeChild(detachedRoot);
child.closestTest("footer"); //null
child.closest("footer"); //<footer>
Run Code Online (Sandbox Code Playgroud)