94

我试图在没有 jquery 的情况下找到具有特定标签名称的最接近的元素。当我单击 a 时,<th>我想访问<tbody>该表。建议?我阅读了有关偏移量的信息,但并没有真正理解太多。我应该使用:

假设 th 已经设置为 clicked th 元素

th.offsetParent.getElementsByTagName('tbody')[0]
4

13 回答 13

132

很简单:

el.closest('tbody')

支持除 IE 以外的所有浏览器。
更新:Edge 现在也支持它。

不需要 jQuery。此外,用 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

于 2016-02-09T14:28:58.523 回答
71

派对迟到了一点(非常),但尽管如此。这应该可以解决问题

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;
}
于 2014-06-08T15:13:54.663 回答
22

以下是在不使用 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');
于 2013-09-06T18:11:06.027 回答
9

有一个标准化的函数可以做到这一点:Element.closest。除了 IE11 之外的大多数浏览器都支持它(caniuse.com 的详细信息)。MDN 文档还包含一个 polyfill ,以防您必须针对较旧的浏览器。

要找到给定的最接近的tbody父母,th您可以这样做:

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");
于 2014-08-08T14:42:23.320 回答
6
function closest(el, sel) {
    if (el != null)
        return el.matches(sel) ? el 
            : (el.querySelector(sel) 
                || closest(el.parentNode, sel));
}

这个解决方案使用了 HTML 5 规范的一些更新的特性,并且在旧的/不兼容的浏览器(阅读:Internet Explorer)上使用它需要一个 polyfill。

Element.prototype.matches = (Element.prototype.matches || Element.prototype.mozMatchesSelector 
    || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector 
    || Element.prototype.webkitMatchesSelector || Element.prototype.webkitMatchesSelector);
于 2014-11-18T15:07:18.650 回答
3

扩展@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;
}
于 2015-07-30T12:17:48.797 回答
2

这是我正在使用的简单功能:-

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;
}
于 2015-04-19T08:14:08.393 回答
2

概括:

为了找到一个特定的祖先,我们可以使用:

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>

于 2018-09-16T07:20:12.667 回答
1

在包含类、ID、数据属性或标签的树中获取最近的 DOM 元素。包括元素本身。支持回 IE6。

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');
于 2015-04-15T18:35:25.407 回答
1

查找最近的元素子节点。

closest: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;

}

于 2016-08-17T10:40:29.283 回答
0

这里。

function findNearest(el, tag) {
    while( el && el.tagName && el.tagName !== tag.toUpperCase()) {
        el = el.nextSibling;     
    } return el;
} 

仅在树的下方找到兄弟姐妹。使用previousSibling去另一种方式或使用变量来遍历两种方式并返回先找到的那个。你得到了一般的想法,但是如果你想遍历 parentNodes 或者如果兄弟姐妹不匹配,你也可以使用 jQuery。在这一点上,它很容易值得。

于 2013-09-07T16:45:56.107 回答
0

聚会有点晚了,但是当我路过并回答一个非常相似的问题时,我把我的解决方案放在这里 - 我们可以说这是 JQueryclosest()方法,但在普通的好 ol' JavaScript 中。

它不需要任何 pollyfills 并且它是较旧的浏览器,并且 IE (:-) ) 友好: https ://stackoverflow.com/a/48726873/2816279

于 2018-02-11T00:04:45.343 回答
-5

我认为最容易用 jquery 捕获的代码最接近:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
    $(document).ready(function () {
        $(".add").on("click", function () {
            var v = $(this).closest(".division").find("input[name='roll']").val();
            alert(v);
        });
    });
</script>
<?php

for ($i = 1; $i <= 5; $i++) {
    echo'<div class = "division">'
        . '<form method="POST" action="">'
        . '<p><input type="number" name="roll" placeholder="Enter Roll"></p>'
        . '<p><input type="button" class="add" name = "submit" value = "Click"></p>'
        . '</form></div>';
}
?>

非常感谢。

于 2018-09-19T04:39:17.347 回答