news 2026/5/8 16:08:52

跟着 MDN 学 HTML day_28:(使用选择器 API 在 DOM 树中进行选择与遍历)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
跟着 MDN 学 HTML day_28:(使用选择器 API 在 DOM 树中进行选择与遍历)

引言

在早期的前端开发中,要通过 JavaScript 获取页面中的特定元素,往往需要编写循环遍历的代码,或者依赖 getElementById、getElementsByClassName 等方法进行多次调用。随着 Selectors API 的引入,开发者可以直接使用 CSS 选择器语法来查询 DOM 树中的元素,这使得元素查找变得更加高效和直观。本文将详细介绍 querySelector 和 querySelectorAll 这两个核心方法,以及使用选择器时需要注意的细节。

一、NodeSelector 接口与两个核心方法

Selectors API 为所有实现了 Document、DocumentFragment 和 Element 接口的对象添加了两个新方法。这意味着不仅可以在整个文档中进行查询,还可以在特定的文档片段或元素子树中进行局部查询。

<divid="container"><pclass="intro">第一段介绍文字</p><pclass="content">第二段正文内容</p><spanclass="content">这是一个 span 元素</span></div><script>// querySelector 返回第一个匹配的元素constfirstContent=document.querySelector('.content');console.log(firstContent.textContent);// "第二段正文内容"(p 元素在前)// 如果没有匹配的元素,返回 nullconstnotFound=document.querySelector('.nonexistent');console.log(notFound);// null// querySelectorAll 返回所有匹配的元素constallContent=document.querySelectorAll('.content');console.log(allContent.length);// 2(p 和 span)allContent.forEach(el=>{console.log(el.tagName,el.textContent);});// P 第二段正文内容// SPAN 这是一个 span 元素// 如果没有匹配的元素,返回空的 NodeListconstemptyResult=document.querySelectorAll('.nonexistent');console.log(emptyResult.length);// 0</script>

querySelector 始终返回第一个匹配的元素,如果查找目标是唯一元素(如通过 ID 查询),这个方法是最高效的选择。querySelectorAll 则返回所有匹配元素的集合,适合批量操作场景。

二、在特定子树中进行查询

查询方法可以基于任意元素节点调用,而不仅仅局限于 document 对象。这样可以将搜索范围限制在特定的 DOM 子树中,提高查询效率并避免意外匹配到范围外的元素。

<articleid="post-1"><h2class="title">文章一的标题</h2><pclass="summary">文章一的摘要</p></article><articleid="post-2"><h2class="title">文章二的标题</h2><pclass="summary">文章二的摘要</p></article><script>constpost1=document.getElementById('post-1');constpost2=document.getElementById('post-2');// 在 post-1 的子树中查询,不会匹配到 post-2 的元素consttitleInPost1=post1.querySelector('.title');console.log(titleInPost1.textContent);// "文章一的标题"constsummaryInPost2=post2.querySelector('.summary');console.log(summaryInPost2.textContent);// "文章二的摘要"// 子树查询不会包含调用节点本身,只搜索其子节点// 下面的查询在 post-1 内部查找 article 元素constarticleInside=post1.querySelector('article');console.log(articleInside);// null(post-1 本身不会被匹配)</script>

在复杂页面中,限定查询范围可以显著减少浏览器需要遍历的节点数量。当处理动态加载的内容或组件时,在组件根元素上调用查询方法是一种良好的实践。

三、querySelectorAll 返回的是静态 NodeList

与其他 DOM 方法(如 getElementsByClassName)返回的动态 HTMLCollection 不同,querySelectorAll 返回的是一个静态的 NodeList。这意味着获取结果后,后续对 DOM 的修改不会自动反映到这个列表中。

<ulid="task-list"><liclass="task">任务一</li><liclass="task">任务二</li></ul><buttonid="add-task">添加任务</button><buttonid="check-static">检查静态列表</button><script>consttaskList=document.getElementById('task-list');constaddBtn=document.getElementById('add-task');constcheckBtn=document.getElementById('check-static');// 通过 querySelectorAll 获取静态 NodeListconststaticTasks=document.querySelectorAll('.task');console.log('初始数量:',staticTasks.length);// 2// 通过 getElementsByClassName 获取动态 HTMLCollectionconstliveTasks=document.getElementsByClassName('task');console.log('动态集合初始数量:',liveTasks.length);// 2addBtn.addEventListener('click',()=>{constnewTask=document.createElement('li');newTask.className='task';newTask.textContent=`任务${taskList.children.length+1}`;taskList.appendChild(newTask);console.log('添加后动态集合数量:',liveTasks.length);// 3(自动更新)});checkBtn.addEventListener('click',()=>{console.log('静态列表数量:',staticTasks.length);// 始终为 2// 需要重新查询才能获取最新的元素constrefreshed=document.querySelectorAll('.task');console.log('重新查询后数量:',refreshed.length);});</script>

静态特性有时是优点:如果需要在遍历 NodeList 的同时修改 DOM 结构,静态列表可以避免因集合动态变化而导致的遍历问题。但如果需要始终反映最新的 DOM 状态,则需要重新执行查询。

四、灵活使用选择器列表

两个查询方法都支持选择器列表,可以在一次调用中使用多个逗号分隔的选择器,匹配其中任意一个的元素都会被返回。

<divid="dashboard"><buttonclass="primary">主要操作</button><buttonclass="secondary">次要操作</button><aclass="primary"href="/more">了解更多</a><spanclass="secondary">提示信息</span></div><script>// 通过逗号分隔的选择器列表,一次性匹配多种元素constclickableElements=document.querySelectorAll('button.primary, a.primary, button.secondary');console.log('可交互元素数量:',clickableElements.length);// 3clickableElements.forEach(el=>{console.log(el.tagName,el.className);});// BUTTON primary// BUTTON secondary// A primary// 选择器列表在 querySelector 中同样适用// 返回按文档顺序第一个匹配的元素constfirstInteractive=document.querySelector('span.secondary, a.primary, button.primary');console.log(firstInteractive.tagName,firstInteractive.className);// BUTTON primary(按照文档顺序,button.primary 先出现)</script>

选择器列表中的每个选择器都是独立匹配的,最终的排列顺序由元素在文档中的先后位置决定,而非选择器在列表中的书写顺序。这一特性在需要同时关注多种类型元素时非常实用。

五、通过 ID 进行查询

使用选择器 API 可以通过 ID 选择器来查找元素,甚至可以一次传入多个 ID 选择器,返回第一个存在于文档中的匹配元素。

<divid="section-a">这是 A 区域</div><!-- 注意:文档中没有 id="section-b" 的元素 --><divid="section-c">这是 C 区域</div><script>// 单个 ID 查询constsectionA=document.querySelector('#section-a');console.log(sectionA.textContent);// "这是 A 区域"// 使用多个 ID 选择器:返回第一个在文档中存在的元素constfirstSection=document.querySelector('#section-b, #section-c, #section-a');console.log(firstSection.textContent);// "这是 C 区域"(section-c 在文档顺序中先于 section-a 出现且存在)// 如果所有 ID 都不存在,返回 nullconstmissing=document.querySelector('#nonexistent-1, #nonexistent-2');console.log(missing);// null// 相比 getElementById 的优势:可以一次尝试多个 ID// 等效的传统写法需要多次调用和条件判断constel=document.getElementById('section-b')||document.getElementById('section-c')||document.getElementById('section-a');console.log(el.textContent);// "这是 C 区域"</script>

使用多 ID 选择器可以简化一些防御性编程场景:当不确定页面上是否存在某个 ID 时,可以按优先级列出备选 ID,浏览器会返回第一个存在的元素。这比手动编写多个 getElementById 调用的回退逻辑更加简洁。

六、伪类选择器的限制

出于隐私保护和安全性考虑,选择器 API 对某些伪类选择器的支持有限制。特别是 :visited 伪类不会返回任何匹配结果,而 :link 会被当作 :any-link 处理。

<nav><ahref="https://example.com"class="external">外部链接(未访问)</a><ahref="https://developer.mozilla.org"class="external">MDN 链接</a><ahref="/local"class="local">内部链接</a></nav><script>// :link 伪类会被当作 :any-link 处理 const allLinks = document.querySelectorAll('a:link'); console.log('匹配到的链接数量:', allLinks.length); // 可能匹配所有带有 href 属性的 a 元素 // :visited 伪类不会返回任何匹配结果 const visitedLinks = document.querySelectorAll('a:visited'); console.log('visited 匹配数量:', visitedLinks.length); // 0(始终为空) // 这种限制防止了恶意网站通过检测链接样式来窥探用户浏览历史 // 在开发中应避免依赖 :visited 进行元素选择 // 可以正常使用的结构伪类 const firstLink = document.querySelector('a:first-of-type'); console.log(firstLink.textContent); // "外部链接(未访问)" const noHrefLinks = document.querySelectorAll('a:not([href])'); console.log('没有 href 的链接数量:', noHrefLinks.length);&lt;/script&gt;

了解这些限制可以帮助开发者避免在元素查询中编写无效的选择器。如果需要根据链接状态来改变行为,应该在 CSS 层面处理样式,在 JavaScript 层面通过其他数据属性来标记状态。

总结

Selectors API 是现代 Web 开发中进行 DOM 查询的基石,它让元素查找变得像编写 CSS 一样自然。本文涵盖的核心要点包括:

querySelector 返回子树中第一个匹配的元素,未找到时返回 null。querySelectorAll 返回所有匹配元素的静态 NodeList,未找到时返回空列表。这两个方法可以在 Document、DocumentFragment 和 Element 上调用,支持在特定子树中限定查询范围。返回的 NodeList 是静态的,DOM 的后续变化不会自动反映到已获取的集合中。选择器列表允许在一次调用中组合多个选择器,匹配顺序由文档结构而非选择器书写顺序决定。多 ID 选择器可以简化需要回退查找的场景。出于隐私保护,:visited 伪类始终返回空结果,:link 会被当作 :any-link 处理。

掌握这些知识后,开发者可以告别冗长的循环遍历代码,用简洁高效的选择器语法精确地定位到目标元素。


想要解锁更多HTML 核心标签实战、前端零基础入门干货、开发避坑全指南吗?
持续关注,后续将更新CSS 布局实战、JavaScript 交互基础、全站导航开发等硬核内容,带你从新手快速进阶,轻松搞定前端开发!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 16:07:50

手把手教你搞定SF2507V的RGMII接口调试:从硬件查线到软件delay调优

SF2507V RGMII接口调试实战&#xff1a;从信号完整性到时序优化的全流程指南 在嵌入式网络设备开发中&#xff0c;RGMII接口的稳定性直接决定了千兆以太网的传输质量。作为连接MAC与PHY的关键桥梁&#xff0c;RGMII接口调试往往成为硬件工程师的"噩梦"——信号完整性…

作者头像 李华