获取子节点的最佳方法

2020/10/11 20:21 · javascript ·  · 0评论

我想知道,JavaScript提供了多种方法来从任何元素中获取第一个子元素,但是哪种方法最好呢?最好的意思是:在行为方面,大多数跨浏览器兼容,最快,最全面且可预测。我用作别名的方法/属性的列表:

var elem = document.getElementById('container');
var child = elem.children[0];
var child = elem.firstElementChild; // == children[0]

这适用于两种情况:

var child = elem.childNodes[0]; // or childNodes[1], see below

在表单或<div>迭代的情况下如果我可能遇到文字元素:

var child = elem.childNodes; // treat as NodeList
var child = elem.firstChild;

据我所知,firstChild使用来自的NodeListchildNodesfirstElementChild使用children我将这一假设基于MDN参考:

childNode是对元素节点的第一个子元素的引用,或者null如果不存在。

我猜想,就速度而言,差异(如果有的话)几乎是零,因为firstElementChild实际上是对的引用children[0],并且该children对象无论如何已经在内存中。

扔给我的是childNodes物体。我用它来查看表格元素中的表单。虽然children列出了所有表单元素,但childNodes似乎还包含HTML代码中的空格:

console.log(elem.childNodes[0]);
console.log(elem.firstChild);

两者都记录 <TextNode textContent="\n ">

console.log(elem.childNodes[1]);
console.log(elem.children[0]);
console.log(elem.firstElementChild);

所有日志<input type="text"... >怎么会?我知道一个对象将允许我使用“原始” HTML代码,而另一个对象则坚持使用DOM,但是该childNodes元素似乎在两个级别上都可以工作。

回到我最初的问题,我的猜测是:如果我想要最全面的对象,那childNodes是要走的路,但是由于它的全面性,就返回我想要的元素而言,它可能不是最可预测的期望在任何给定的时刻。在这种情况下,跨浏览器支持也可能是一个挑战,尽管我可能是错的。

谁能澄清一下手头物体之间的区别?如果存在速度差异,但可以忽略不计,我也想知道。如果我发现这一切都不对,请随时教育我。


PS:拜托,拜托,我喜欢JavaScript,是的,我想处理这种事情。诸如“ jQuery为您处理此问题”之类的答案不是我想要的,因此没有 标签。

听起来您想得太多了。你观察到的区别childNodeschildren,这是一个childNodes包含所有节点,包括完全由空白的文本节点,而children只是对元素的子节点的集合。这就是全部。

尽管有几个问题需要注意,但两个集合都没有不可预测的问题:

  • IE <= 8不包含纯空白文本节点,childNodes而其他浏览器则包含
  • IE <= 8内包含注释节点,children而其他浏览器仅包含元素

childrenfirstElementChild而朋友只是方便,提供了仅限于元素的DOM过滤视图。

firstElementChild可能在IE <9中不可用(仅firstChild)

IE <9上的firstChild是firstElementChild,因为MS DOM(IE <9)没有存储空文本节点。但是,如果您在其他浏览器上这样做,它们将返回空文本节点。

我的解决方案


child=(elem.firstElementChild||elem.firstChild)

即使在IE <9的情况下,这也能使第一个孩子

跨浏览器的方法是使用childNodes获取NodeList,然后使用nodeType ELEMENT_NODE构成所有节点的数组

/**
 * Return direct children elements.
 *
 * @param {HTMLElement}
 * @return {Array}
 */
function elementChildren (element) {
    var childNodes = element.childNodes,
        children = [],
        i = childNodes.length;

    while (i--) {
        if (childNodes[i].nodeType == 1) {
            children.unshift(childNodes[i]);
        }
    }

    return children;
}

http://jsfiddle.net/s4kxnahu/

如果您正在使用实用程序库,例如lodash,这特别容易

/**
 * Return direct children elements.
 *
 * @param {HTMLElement}
 * @return {Array}
 */
function elementChildren (element) {
    return _.where(element.childNodes, {nodeType: 1});
}

未来:

可以querySelectorAll:scope伪类结合使用(匹配作为选择器参考点的元素):

parentElement.querySelectorAll(':scope > *');

在撰写本文时,Chrome,Firefox和Safari:scope支持功能

只是为了增加其他答案,这里仍然存在值得注意的差异,特别是在处理<svg>元素时。

我已经使用了.childNodes和,.children并且更喜欢使用getterHTMLCollection传递的内容.children

然而今天,我遇到了与IE /边缘使用时失败的问题.children<svg>虽然.children在IE被支撑在基本的HTML元素,它不支持文件/文件的片段,SVG元素

对我来说,我可以轻松获取所需的元素,.childNodes[n]因为我没有多余的文本节点可担心。您也许可以做同样的事情,但是正如上面其他地方提到的那样,请不要忘记您可能会遇到意外的因素。

希望这对尝试找出.children现代IE为什么在其js的其他地方起作用而在文档或SVG元素上失败的人有所帮助

嘿,伙计们不要让空格欺骗您。只需在控制台浏览器中进行测试即可。使用本地javascript。这是带有相同类的两个“ ul”集的示例。您无需将'ul'列表全部放在一行中来避免空格,只需使用数组计数跳过空格即可。

如何绕过白色空间querySelector()childNodes[]js的小提琴链接:https://jsfiddle.net/aparadise/56njekdo/

var y = document.querySelector('.list');
var myNode = y.childNodes[11].style.backgroundColor='red';

<ul class="list">
    <li>8</li>
    <li>9</li>
    <li>100</li>
</ul>

<ul class="list">
    <li>ABC</li>
    <li>DEF</li>
    <li>XYZ</li>
</ul>
本文地址:http://javascript.askforanswer.com/huoquzijiediandezuijiafangfa.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!