我正在尝试找到最接近的特定标签元素,而不使用jquery。当我单击一个<th>
时,我想要访问该表格的<tbody>
。有什么建议吗?我读过offset,但并没有真正理解它。我应该只使用:
假设th已经设置为点击的th元素
th.offsetParent.getElementsByTagName('tbody')[0]
我正在尝试找到最接近的特定标签元素,而不使用jquery。当我单击一个<th>
时,我想要访问该表格的<tbody>
。有什么建议吗?我读过offset,但并没有真正理解它。我应该只使用:
假设th已经设置为点击的th元素
th.offsetParent.getElementsByTagName('tbody')[0]
非常简单:
el.closest('tbody')
除IE外,所有浏览器都支持此功能。
更新:Edge现在也支持它了。
无需jQuery。
此外,将jQuery的$(this).closest('tbody')
替换为$(this.closest('tbody'))
将提高性能,特别是当未找到元素时。
IE的Polyfill:
if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector;
if (!Element.prototype.closest) Element.prototype.closest = function (selector) {
var el = this;
while (el) {
if (el.matches(selector)) {
return el;
}
el = el.parentElement;
}
};
请查看:
请注意,如果未找到元素,则没有return
,在最近的元素未找到时会有效地返回undefined
。
更多详情请参见: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
虽然来晚了一点,但这样应该可以 解决:
function closest(el, selector) {
var matchesFn;
// find vendor prefix
['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
if (typeof document.body[fn] == 'function') {
matchesFn = fn;
return true;
}
return false;
})
var parent;
// traverse parents
while (el) {
parent = el.parentElement;
if (parent && parent[matchesFn](selector)) {
return parent;
}
el = parent;
}
return null;
}
el
。for (var parent = el; parent !== null && !parent[matchesFn](selector); parent = el.parentElement) {
el = parent;
}
return parent;
- nevfparent
! - Steven Luel.parentNode
,否则代码会出错。 - smcka以下是在不使用 jQuery 的情况下获取最接近指定标签名的元素的方法:
function getClosest(el, tag) {
// this is necessary since nodeName is always in upper case
tag = tag.toUpperCase();
do {
if (el.nodeName === tag) {
// tag name is found! let's return it. :)
return el;
}
} while (el = el.parentNode);
// not found :(
return null;
}
getClosest(th, 'tbody');
th.closest('tbody');
如果您想自己编写函数-这是我想到的:
function findClosestParent (startElement, fn) {
var parent = startElement.parentElement;
if (!parent) return undefined;
return fn(parent) ? parent : findClosestParent(parent, fn);
}
findClosestParent(x, element => return element.tagName === "SECTION");
function closest(el, sel) {
if (el != null)
return el.matches(sel) ? el
: (el.querySelector(sel)
|| closest(el.parentNode, sel));
}
这个解决方案使用了HTML5规范中的一些新特性,如果在老旧/不兼容的浏览器(即:Internet Explorer)上使用,将需要一个polyfill。
Element.prototype.matches = (Element.prototype.matches || Element.prototype.mozMatchesSelector
|| Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector
|| Element.prototype.webkitMatchesSelector || Element.prototype.webkitMatchesSelector);
function closest(el, selector) {
var matches = el.webkitMatchesSelector ? 'webkitMatchesSelector' : (el.msMatchesSelector ? 'msMatchesSelector' : 'matches');
while (el.parentElement) {
if (el[matches](selector)) return el;
el = el.parentElement;
}
return null;
}
为了查找特定的祖先,我们可以使用以下方法:
Element.closest();
该函数以CSS选择器字符串作为参数。然后返回与传递给参数的CSS选择器匹配的当前元素(或元素本身)的最近祖先。如果没有祖先,则返回null
。
const child = document.querySelector('.child');
// select the child
console.dir(child.closest('.parent').className);
// check if there is any ancestor called parent
<div class="parent">
<div></div>
<div>
<div></div>
<div class="child"></div>
</div>
</div>
扩展@SalmanPK的答案:
它将允许使用节点作为选择器,特别是在处理诸如鼠标悬停之类的事件时非常有用。
function closest(el, selector) {
if (typeof selector === 'string') {
matches = el.webkitMatchesSelector ? 'webkitMatchesSelector' : (el.msMatchesSelector ? 'msMatchesSelector' : 'matches');
while (el.parentElement) {
if (el[matches](selector)) {
return el
};
el = el.parentElement;
}
} else {
while (el.parentElement) {
if (el === selector) {
return el
};
el = el.parentElement;
}
}
return null;
}
var getClosest = function (elem, selector) {
var firstChar = selector.charAt(0);
// Get closest match
for ( ; elem && elem !== document; elem = elem.parentNode ) {
// If selector is a class
if ( firstChar === '.' ) {
if ( elem.classList.contains( selector.substr(1) ) ) {
return elem;
}
}
// If selector is an ID
if ( firstChar === '#' ) {
if ( elem.id === selector.substr(1) ) {
return elem;
}
}
// If selector is a data attribute
if ( firstChar === '[' ) {
if ( elem.hasAttribute( selector.substr(1, selector.length - 2) ) ) {
return elem;
}
}
// If selector is a tag
if ( elem.tagName.toLowerCase() === selector ) {
return elem;
}
}
return false;
};
var elem = document.querySelector('#some-element');
var closest = getClosest(elem, '.some-class');
var closestLink = getClosest(elem, 'a');
var closestExcludingElement = getClosest(elem.parentNode, '.some-class');
switch
语句来代替所有的IF
条件语句,针对firstChar
呢? - Rafael Herscoviciclosest:function(el, selector,userMatchFn) {
var matchesFn;
// find vendor prefix
['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
if (typeof document.body[fn] == 'function') {
matchesFn = fn;
return true;
}
return false;
});
function findInChilds(el){
if(!el) return false;
if(el && el[matchesFn] && el[matchesFn](selector)
&& userMatchFn(el) ) return [el];
var resultAsArr=[];
if(el.childNodes && el.childNodes.length){
for(var i=0;i< el.childNodes.length;i++)
{
var child=el.childNodes[i];
var resultForChild=findInChilds(child);
if(resultForChild instanceof Array){
for(var j=0;j<resultForChild.length;j++)
{
resultAsArr.push(resultForChild[j]);
}
}
}
}
return resultAsArr.length?resultAsArr: false;
}
var parent;
if(!userMatchFn || arguments.length==2) userMatchFn=function(){return true;}
while (el) {
parent = el.parentElement;
result=findInChilds(parent);
if (result) return result;
el = parent;
}
return null;
}
parentNode
:https://developer.mozilla.org/zh-CN/docs/Web/API/Node.parentNode - Ivan Chernykhel.closest('tbody')
方法可以用于查找最近的祖先<tbody>
元素。以下是更详细的解释和polyfill实现。 - oriadam