马黑黑 发表于 2026-6-29 12:43

获取容器元素的子节点

<style>
    .artBox { margin: 20px auto; max-width: 1200px; font: normal 18px/26px sans-serif; }
    .artBox mark { padding: 2px 6px; background: #ccc; }
    .artBox blockquote { padding: 14px; border: solid gray; border-width: 0 4px; border-radius: 10px; background: #ddd; }
    .artBox p { margin: 10px 0; }
</style>

<div class="artBox"><blockquote>在网页结构中,HTML容器元素就像“收纳盒”,用于组织和包裹内容,使页面结构更清晰,方便后续的样式和交互处理。通俗一点讲,容器元素就是可以装载其它元素的元素。</blockquote>
    <p>最常用的容器元素之一是 <mark>&lt;div&gt;</mark>,它是块级(block)元素,默认独占一行,没有明显的语义含义,常用于布局和分组。本文以 div 元素为例,简单介绍其内子节点的获取。请看如下示例:</p>
    <div class="hEdiv" data-prev="1"><pre class="hEpre">
&lt;div id="ma" title="点击查看子节点信息"&gt;
    &lt;p&gt;这行是一个 p 标签,它是 id="ma" 的 div 容器的标签节点(亦可称元素节点)。&lt;/p&gt;
    &lt;div&gt;这是一个 div 节点,内含纯文本。下一个标签节点是一个 img 标签:&lt;/div&gt;
    &lt;img src="https://638183.freep.cn/638183/small/dolan.png" alt=""&gt;
&lt;/div&gt;

&lt;script&gt;
    const ma = document.getElementById('ma');
    ma.onclick = () =&gt; {
      let msg = 'id="ma" 的 div 包含如下子标签节点:\n\n';
      const nodes = ma.children;
      [...nodes].forEach((n, k) =&gt; msg += `${k+1}. ${n.tagName}\n`);
      alert(msg);
    };
&lt;/script&gt;
    </pre></div>
    <p>重点观察 div 标签包裹的子标签,后面的JS仅是交互辅助。从 DIV 的 HTML 代码结构看,我们真真切切看到了三个子标签:p、div和img,它们依次出现在 div 标签之内、被 div 标签所包裹,是 div 的子元素。预览查看效果时点击id="ma"的 div,弹出的信息框会给出所有子标签节点的标签名。</p>
    <p>示例中的JS,先获得 id="ma" 的容器元素 ma,ma 的点击事件则通过 <mark>children</mark> 属性获得其内所有标签(元素)节点,并将其标签名(tagName)取出。</p>
    <blockquote>元素的 children 是一个常用的属性或方法,用于获取某个元素的所有直接子元素。它在原生 JavaScript 和 jQuery 中均有实现,主要用于操作 DOM 树。</blockquote>
    <p><mark>element.children</mark> 即<b>元素子节点</b>属性拿到的是子元素节点(<mark>children</mark> 是 child 即孩子的复数形式)。但需要注意:<b>容器元素内的子节点不全然是元素节点</b>。以下示例,HTML代码结构和第一例的一样,但在JS中使用元素的 <mark>childNodes</mark> 即<b>子节点属性</b>获取节点名称(<mark>nodeName</mark>)——不是第一例的标签名,因为有些节点可能不是元素节点。可以在打开预览页面后点击 div 容器元素,比较弹出的信息和上例弹出信息的区别:</p>
    <div class="hEdiv" data-prev="1"><pre class="hEpre">
&lt;div id="ma" title="点击查看子节点信息"&gt;
    &lt;p&gt;这行是一个 p 标签,它是 id="ma" 的 div 容器的标签节点(亦可称元素节点)。&lt;/p&gt;
    &lt;div&gt;这是一个 div 节点,内含纯文本。下一个标签节点是一个 img 标签:&lt;/div&gt;
    &lt;img src="https://638183.freep.cn/638183/small/dolan.png" alt=""&gt;
&lt;/div&gt;

&lt;script&gt;
    const ma = document.getElementById('ma');
    ma.onclick = () =&gt; {
      let msg = 'id="ma" 的 div 包含如下子节点:\n\n';
      const nodes = ma.childNodes;
      [...nodes].forEach((n, k) =&gt; msg += `${k+1}. ${n.nodeName}\n`);
      alert(msg);
    };
&lt;/script&gt;
    </pre></div>
    <p>可以看到,节点变多一倍不止,多出来的全是 <mark>#text</mark> 文本节点,这些 #text 子节点基于示例的 HTML 代码结构,编号1的 #text 是 p 标签和 容器 div 之间的换行符 <mark>\n</mark>,编号3和编号5的 #text 是上下两个元素标签之间的换行符 <mark>\n</mark>,编号7的 #text 是 IMG 标签和容器div收尾符号之间的换行符 <mark>\n</mark>。</p>
    <blockquote>childNodes 属性是一个非常重要的 DOM 属性,它返回一个包含指定节点的所有子节点的 NodeList 对象。这个NodeList 是一个实时的集合,意味着如果 DOM 结构发生变化,NodeList 也会相应地更新</blockquote>
    <p>最后再给出一组 div 容器的示例,各 div 子节点由于代码结构的不同而不同,值得细细研究、领悟:</p>
    <div class="hEdiv" data-prev="1"><pre class="hEpre">
&lt;style&gt;
    div { margin: 10px auto; width: 600px; border: 1px solid gray; padding: 12px; }
&lt;/style&gt;

&lt;div&gt;
    本div只有一个文本节点
&lt;/div&gt;

&lt;div&gt;&lt;p&gt;本div只有一个p元素节点&lt;/p&gt;&lt;/div&gt;

&lt;div&gt;
    &lt;p&gt;本div有头尾两个文本节点,中间是p元素节点&lt;/p&gt;
&lt;/div&gt;

&lt;div&gt;
    这里是文本节点1
    &lt;p&gt;这里是p元素节点&lt;/p&gt;
    这里是文本节点2
&lt;/div&gt;

&lt;div&gt;
    &lt;!-- 这行是注释节点(预览时看不到) --&gt;
    &lt;p&gt;这行p元素节点(上一行是注释行)&lt;/p&gt;
&lt;/div&gt;

&lt;script&gt;
    const divs = document.querySelectorAll('div');
    divs.forEach(div =&gt; {
      div.title = '点击查看节点信息';
      div.onclick = () =&gt; {
            let msg = '本 div 包含如下子标签节点:\n\n';
            const nodes = div.childNodes;
            [...nodes].forEach((n, k) =&gt; msg += `${k+1}. ${n.nodeName}\n`);
            alert(msg);
      };
    });
&lt;/script&gt;
    </pre></div>
    <p>小结:容器元素可以包含很多类型的子节点,通过 <mark>element.children</mark> 属性可以获取其内的子 element 即子元素节点,而 <mark>element.childNodes</mark> 属性则返回所有节点——包括文本节点、标签节点和注释节点等。特别注意:当子节点中包含有元素节点且元素节点独占一行时,其上、下均存在换行<b>文本节点</b>(<mark>\n</mark>)。</p>
</div>

<script type="module">
    import hl from 'https://638183.freep.cn/638183/web/js/hl.js';
    const divs = document.querySelectorAll('.hEdiv');
    const pres = document.querySelectorAll('.hEpre');
    divs.forEach((div,idx) => hl.hl(div, pres));
</script>

红影 发表于 2026-6-29 15:35

预览里能看到返回的子元素节点或所有节点,只是不知道获取这些是派什么用的呢?{:4_204:}

梦江南 发表于 2026-6-29 16:56

对节点两字很陌生,查询了一下,是不是这个意思:节点是网络或系统中的连接点或功能单元,用于发送、接收或转发信息,也可表示数据结构或图中的基本单元。

霜染枫丹 发表于 2026-6-29 18:15

感谢马老师的耐心拆解科普!通过这一阵子学习播放器的制作,对马老师的解析能够理解一些。我应该记住这些层次秩序的关系,对我制作也有很大的帮助。虽然我写不出来一个完整的作品,但对于想达到自己想要的结果这是必不可少的步骤。我也在看一些教程,但那些教程不是对我这样零基础的人写的,没有您这个好理解,

谢谢您的无私分享,我会抱走。辛苦了,祝您夏安!{:4_204:}{:4_190:}

马黑黑 发表于 2026-6-29 19:37

霜染枫丹 发表于 2026-6-29 18:15
感谢马老师的耐心拆解科普!通过这一阵子学习播放器的制作,对马老师的解析能够理解一些。我应该记住这些层 ...

感谢支持。晚上好

马黑黑 发表于 2026-6-29 19:43

梦江南 发表于 2026-6-29 16:56
对节点两字很陌生,查询了一下,是不是这个意思:节点是网络或系统中的连接点或功能单元,用于发送、接收或 ...
这是两种不同的节点,概念和应用层面都不同。

你说的节点,是现实生活中的节点。例如,移动运营商的基站,每一个站点都是节点,也正因为有了一个又一个信号可以衔接起来“节点”,我们的手机信号在哪里都通。

我说的时网页结构内部的节点。比如你做帖子,帖子容器大概是一个 div 标签,它里面有很多可见和不可见的节点,可见的节点像图片、视频、文字,还有很多不可见的如换行符、代码注释等。网页结构的节点是构成网页可视效果的组成部分,其原理当然也来源于现实生活,但确实概念不同、层面不一样。

马黑黑 发表于 2026-6-29 19:50

红影 发表于 2026-6-29 15:35
预览里能看到返回的子元素节点或所有节点,只是不知道获取这些是派什么用的呢?
我举一个不太恰当但可以说明问题的例子:

医生诊断病人肋骨哪一根断了,他得一根一根地看,最后查出是哪一根出了问题常,这就是“遍历”肋骨。”遍历“肋骨得有基础:拿到肋骨的医学影像图片,然后在其上用眼扫描(遍历)。X光拍照就相当于获取肋骨影像的手段,因此,你的问题就是,拍X光照派什么用途。

红影 发表于 2026-6-29 23:04

马黑黑 发表于 2026-6-29 19:50
我举一个不太恰当但可以说明问题的例子:

医生诊断病人肋骨哪一根断了,他得一根一根地看,最后查出是 ...

嗯,代码制作里也需要这样的X光照,来判断或查找需要的内容{:4_204:}

梦江南 发表于 2026-6-30 07:14

马黑黑 发表于 2026-6-29 19:43
这是两种不同的节点,概念和应用层面都不同。

你说的节点,是现实生活中的节点。例如,移动运营商的基 ...

谢谢黑黑老师详细耐心解说。知道了。早上嚎!{:4_180:}

杨帆 发表于 2026-6-30 11:23

长知识~谢谢马老师直观对比讲解element.children 与 element.childNodes 属性{:4_190:}

马黑黑 发表于 2026-6-30 19:26

杨帆 发表于 2026-6-30 11:23
长知识~谢谢马老师直观对比讲解element.children 与 element.childNodes 属性

这两个属性都基于元素层级,在操作DOM文档模型中非常有用

马黑黑 发表于 2026-6-30 19:27

梦江南 发表于 2026-6-30 07:14
谢谢黑黑老师详细耐心解说。知道了。早上嚎!

晚上你也嚎嚎

马黑黑 发表于 2026-6-30 19:30

红影 发表于 2026-6-29 23:04
嗯,代码制作里也需要这样的X光照,来判断或查找需要的内容

差不多吧,反正都是扫描。

在足球场上找掉落的绣花针,在确定可能的区域之后,最好的扫描方法就是把目标区域划分为一个个的小型矩形,然后一个一个矩形地搜索。这些小矩形就是我们要遍历的对象,而遍历它们之前,先得拿到每一个矩形。

杨帆 发表于 2026-6-30 20:20

马黑黑 发表于 2026-6-30 19:26
这两个属性都基于元素层级,在操作DOM文档模型中非常有用

是的,谢谢马老师{:4_180:}

马黑黑 发表于 2026-6-30 20:29

杨帆 发表于 2026-6-30 20:20
是的,谢谢马老师

{:4_190:}

淡墨疏影 发表于 2026-6-30 21:20

教程讲的透彻,表述清晰,这样的文章很难找,谢分享。

红影 发表于 2026-7-1 10:01

马黑黑 发表于 2026-6-30 19:30
差不多吧,反正都是扫描。

在足球场上找掉落的绣花针,在确定可能的区域之后,最好的扫描方法就是把目 ...

容器元素就是这样的矩形吧{:4_204:}

马黑黑 发表于 2026-7-1 12:25

红影 发表于 2026-7-1 10:01
容器元素就是这样的矩形吧

可以这么理解

马黑黑 发表于 2026-7-1 12:26

淡墨疏影 发表于 2026-6-30 21:20
教程讲的透彻,表述清晰,这样的文章很难找,谢分享。

一般都会有的

红影 发表于 2026-7-3 20:51

马黑黑 发表于 2026-7-1 12:25
可以这么理解

嗯嗯,谢谢黑黑{:4_204:}
页: [1] 2 3 4
查看完整版本: 获取容器元素的子节点