在没有jQuery的情况下查找最近的元素

IT技术 javascript
2021-01-22 19:58:45

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

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

th.offsetParent.getElementsByTagName('tbody')[0]
6个回答

很简单的:

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

@stevemoretz。现在最接近的是原生 JavaScript
2021-03-13 19:58:45
这被称为最佳答案!
2021-03-13 19:58:45
最接近的是 jQuery。但是 OP 说没有 jQuery。
2021-03-16 19:58:45
@LouiseEggleton 是的,oop
2021-03-24 19:58:45
为什么这个答案在页面底部?应该在顶部。非常感谢
2021-04-02 19:58:45

聚会有点(非常)迟到,但仍然如此。这应该做的伎俩

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.parentNode否则在 IE 中遍历 SVG 时会中断。
2021-03-18 19:58:45
很好的答案,这是一种享受。MDN 也有一个用于 element.closest() 的 polyfill。Chrome 在当前版本中包含 element.matches(),因此不需要前缀。我刚刚将它添加到我正在开发的应用程序 Clibu 中使用的库中。
2021-03-28 19:58:45
这段代码很好,但它缺少分号并且还在parent全局范围内定义(!)
2021-03-30 19:58:45
我已经更改了代码,以便它还测试eljQuery.closest() 和 Element.closest() 所做的元素for( var parent = el ; parent !== null && !parent[matchesFn](selector) ; parent = el.parentElement ){ el = parent; } return parent;
2021-03-31 19:58:45
可能值得一提:developer.mozilla.org/en-US/docs/Web/API/Element/closest最接近的本地方法,虽然支持很少:Chrome41、FF35、IE-nope、Opera28、Safari9
2021-03-31 19:58:45

以下是在不使用 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');
公平地说,@Jhawins 你对最接近的定义是 jQuery 最接近的定义。这不是一个 jQuery 问题。我无法证明为什么 jQuery 决定最接近的意思是最近的祖先,但更合理的定义是最接近的元素,无论是父元素、前一个兄弟元素、下一个兄弟元素等等。无论找到什么“最接近”目标元素。
2021-03-13 19:58:45
我不相信这会奏效。它只检查 DOM 树。th->thead->table 从不考虑兄弟姐妹
2021-03-22 19:58:45
你应该在你的问题中说明那个特定的案例。
2021-03-26 19:58:45
看。此函数遍历 parentNodes 以找到使用提供的标签的最近父节点(甚至通过扩展)。这不会“向下”文档树,只会“向上”。普通用户最有可能将“最近的”节点视为最近的兄弟节点。他只是不知道他需要的术语。
2021-04-11 19:58:45
@ryandlf 但是,如果您的父母和兄弟姐妹都处于相同的“距离”呢?jQuery 的定义很明确,它最多返回一个匹配项。
2021-04-11 19:58:45

有一个标准化的函数可以做到这一点:Element.closest除 IE11 外的大多数浏览器都支持它(caniuse.com 提供的详细信息)。MDN文档还包括如果你有目标旧版浏览器的一个填充工具。

要找到最接近的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");
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);
嘿,让我清除那个downvote你说什么兄弟
2021-03-14 19:58:45
对我来说很好用,你在哪个浏览器中工作?这在旧浏览器中不受支持
2021-03-16 19:58:45
是的,我会做...你检查过你的小提琴结果,它显示错误......匹配未定义
2021-03-23 19:58:45
它总是排在第一张桌子上。不是最近的表 .. 请参阅此链接jsfiddle.net/guuy5kof
2021-03-30 19:58:45
不错的收获!已修复,请在此处查看jsfiddle.net/c2pqc2x0请像老板一样给我投票:)
2021-04-11 19:58:45