javascript 使用本机 DOM 的最近祖先匹配选择器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15329167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 00:23:44  来源:igfitidea点击:

Closest ancestor matching selector using native DOM?

javascriptjquerystandardsw3cdom-traversal

提问by hurrymaplelad

Is anybody working on a jQuery.closest()equivalent in the DOM api?

有人在 DOM api 中使用jQuery.closest()等价物吗?

Looks like the Selectors Level 2 draftadds matches()equivalent to jQuery.is(), so native closest should be much easier to write. Has adding closest()to Selectors come up?

看起来Selectors Level 2 草案添加了matches()等效于jQuery.is(),所以 native 最接近应该更容易编写。添加closest()到选择器出现了吗?

采纳答案by Pavlo D

Element.closest()

Element.closest()

its support

它的支持

Implementing such function with Element.matches() seems not optimal in terms of performance, cause apparently matches() will make a call to querySelectorAll() every time you test a parent, while only one call is sufficient for the job.

使用 Element.matches() 实现这样的函数在性能方面似乎不是最佳的,因为显然 match() 每次测试父级时都会调用 querySelectorAll(),而只有一次调用就足以完成这项工作。

Here's a polyfill for closest() on MDN. Note a single call to 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;
  };
}

But bear in mind that function implemented like this will not work properly on unattached tree (detached from document.documentElement root)

但请记住,像这样实现的函数在未附加的树上无法正常工作(与 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>   

Though closest() that is implemented in Firefox 51.0.1 seems to work fine with detached tree

尽管在 Firefox 51.0.1 中实现的最接近()似乎与分离树一起工作正常

document.documentElement.removeChild(detachedRoot);
child.closestTest("footer"); //null
child.closest("footer"); //<footer>

回答by Paul Irish

Building off of Alnitak's answer. Here's the working current implementation with matchesSelectorwhich is now matchesin the DOM spec.

基于 Alnitak 的回答。这matchesSelectormatchesDOM 规范中的当前工作实现。

// 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;
}

Browser support is great: http://caniuse.com/matchesselector

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

回答by Jonathan Raoult

Seems like Chrome 40 will bring a native element.closest()method (http://blog.chromium.org/2014/12/chrome-40-beta-powerful-offline-and.html) specified here: https://dom.spec.whatwg.org/#dom-element-closest

好像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

回答by Alnitak

This sounds like it ought to be pretty easy, given the matchesfunction, although that's not widely supported yet:

考虑到该matches功能,这听起来应该很容易,尽管尚未得到广泛支持:

function closest(elem, selector) {
    while (elem) {
        if (elem.matches(selector)) {
            return elem;
        } else {
            elem = elem.parentElement;
        }
    }
    return null;
}

The trouble is, the matchesfunction isn't properly supported. As it's still a relatively new API it's available as webkitMatchesSelectorin Chrome and Safari, and mozMatchesSelectorin Firefox.

问题是,该matches功能没有得到正确支持。由于它仍然是一个相对较新的 API,因此可以webkitMatchesSelector在 Chrome 和 Safari 以及mozMatchesSelectorFirefox 中使用。

回答by Paritosh

Using element.closest() we can find Closest ancestor matching selector. This method takes selectors list as parameter and returns the closest ancestor. As per Rob's Comment this API will be available from chrome 41 and FF 35.

使用 element.closest() 我们可以找到最近的祖先匹配选择器。此方法将选择器列表作为参数并返回最近的祖先。根据 Rob 的评论,此 API 将在 chrome 41 和 FF 35 中可用。

As explained in whatwg specs https://dom.spec.whatwg.org/#dom-element-closest

如 whatwg 规范中所述https://dom.spec.whatwg.org/#dom-element-closest

Example: The below HTML will show alert message "true"

示例:下面的 HTML 将显示警报消息“true”

<html>
    <body>
        <foo>
            <bar>
                <a id="a">
                    <b id="b">
                        <c id="c"></c>
                    </b>
                </a>
            </bar>
         </foo>
    <script>
        var a = document.getElementById('a');
        var b = document.getElementById('b');
        var c = document.getElementById('c');
        alert(c.closest("a, b")==b);
    </script>
    </body>
</html>

回答by Finn Fitzsimons

A little recursion will do the trick.

一点递归就能解决问题。

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

    return function closest(el, selector) {
        return !el ? null :
        matchesSelector.call(el, selector) ? el : closest(el.parentElement, selector);
    };
})();