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
Closest ancestor matching selector using native DOM?
提问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
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 matchesSelector
which is now matches
in the DOM spec.
基于 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;
}
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 matches
function, 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 matches
function isn't properly supported. As it's still a relatively new API it's available as webkitMatchesSelector
in Chrome and Safari, and mozMatchesSelector
in Firefox.
问题是,该matches
功能没有得到正确支持。由于它仍然是一个相对较新的 API,因此可以webkitMatchesSelector
在 Chrome 和 Safari 以及mozMatchesSelector
Firefox 中使用。
回答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);
};
})();