整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

前端:JavaScript - 结点(Node) Vs 元素(Element)

果您在 JavaScript 中使用过 DOM,您可能已经注意到有多种方法可以访问同一个元素(nextSiblingnextElementSibling)这真的很令人困惑,它们之间的区别并不明显,很难决定该用哪个。 在本文中,我将解释一下节点和元素之间的区别。

元素vs结点(Elements vs Nodes)

在这两者中,元素(Element)是最容易理解的,因为它们只是 HTML 元素,例如 div、span 或 body 标签。通常,当您使用 DOM 时,您将使用元素,因为您通常希望与 HTML 元素进行交互。

结点(Nodes)是元素的更通用版本。节点可以是 HTML 元素,但也可以是 HTML 文档中的任何其他内容,例如文本或注释。这使得节点更难使用,因为在使用 DOM 时,您通常不关心文本节点或注释节点之类的东西,而只关心元素节点。由于这个原因,我通常避免使用结点。下面是所有重要结点类型的列表。

  • 元素结点 (Element Node)
  • 文本结点 (Text Node)
  • CData 结点 (CData Section Node)
  • 处理指令结点 (Processing Instruction Node)
  • 注释结点 (Comment Node)
  • 文档结点 (Document Node)
  • 文档类型结点 (Document Type Node)
  • 文档段结点 (Document Fragment Node)

当你在 DOM 中导航时,总是更喜欢选择元素而不是结点的方法。通常这些方法中包含单词元素,或者选择结点的版本中会包含单词结点,以便您区分它们。

HTMLCollection vs NodeList

在遍历 DOM 时,有时会返回一组元素/结点(querySelector、children)。这将是 HTML Collection 或 NodeList。

HTMLCollection 很容易理解,因为它只能包含元素。 getElementsByClassName 和 children 等方法返回一个 HTMLCollection。这些集合与数组非常相似,因此您甚至可能没有意识到您正在使用 HTMLCollection,但 HTMLCollections 缺少数组所具有的所有高阶函数。诸如 forEach、map 和 reduce 之类的东西在 HTMLCollection 上不可用。此外,HTMLCollections 正在实时更新。这意味着如果你有一个包含所有元素的 HTMLCollection,并且你将一个新元素添加到具有该类的 DOM 中,它将自动添加到刚才已经存在的HTMLCollection。老实说,处理起来有点痛苦,因为它可能会导致意想不到的错误。

另一方面,NodeList 可以包含任何类型的结点,包括元素。 NodeList 也类似于数组,但它们同样缺少大多数高阶函数。 NodeList 上唯一的高阶函数是 forEach 函数。返回 NodeLists 的一些方法示例是 querySelectorAll 和 childNodes。 NodeLists 也类似于 HTMLCollections 实时更新,但仅在某些情况下。例如,querySelectorAll 不是实时更新列表,但 childNodes 是实时更新。一般来说,我会尽量避免使用 NodeList,因为它们可以包含非 HTML 元素。

下面是实时更新的示例:

开始的HTML结构如下:

JavaScript如下:

我们可以看到,getElementsByClassName返回的是HTMLCollection, 第一次children有两个元素,然后我们又新增了一个节点,发现第二次显示之前children的HTMLCollection也自动更新了,它现在包含三个元素。

下面我们就改一行上面的代码,用querySelectorAll替换getElementsByClassName,然后你会发现,两次显示的children(NodeList)在更新前后没有任何变化。

在Web开发领域,JavaScript(简称JS)作为一门强大的客户端脚本语言,其重要性不言而喻。JS赋予了网页生命,使其能够响应用户的操作,实现动态内容的加载和展示。而这一切的核心,离不开文档对象模型(DOM)的节点操作。本文旨在探索JS与DOM节点操作的奥秘,通过实践示例和理论解析,帮助你掌握这一前端开发的必备技能。

技术概述

DOM简介

DOM是一种标准,用于表示和修改HTML或XML文档的结构。它将文档解析成树状结构,每个节点代表一个元素或属性,允许JS通过编程方式访问和修改这些节点。

核心特性与优势

  • 动态性:JS可以实时修改DOM,响应用户事件,如点击、输入等。
  • 选择器:提供灵活的节点选择方式,如getElementById, getElementsByClassName, querySelector等。
  • 节点操作:添加、删除、移动和修改节点及其属性,使得页面内容的动态更新变得简单。

示例代码

// 创建一个新的列表项
const li = document.createElement('li');
li.textContent = 'New Item';
document.querySelector('ul').appendChild(li);

技术细节

工作原理

当JS执行DOM操作时,它会查找、创建、修改或删除DOM树中的节点。这种操作会触发浏览器重新计算页面的布局和样式,即重排(reflow)和重绘(repaint)。

难点分析

  • 性能问题:频繁的DOM操作可能导致页面性能下降,特别是在大型应用中。
  • 选择器效率:某些选择器比其他的选择器更耗时,如getElementsByTagName

实战应用

场景描述

假设我们需要一个简单的计数器组件,每当用户点击按钮时,页面上显示的计数就会增加。

代码示例

let count = 0;
const counter = document.getElementById('counter');
const incrementBtn = document.getElementById('increment');

incrementBtn.addEventListener('click', () => {
  count++;
  counter.textContent = count;
});

优化与改进

性能瓶颈

  • 减少DOM操作:尽量减少直接的DOM操作次数,比如使用字符串拼接后一次性更新。
  • 虚拟DOM:借鉴React等框架的虚拟DOM技术,先在内存中操作,最后批量更新真实DOM。

代码示例

let fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
  const div = document.createElement('div');
  div.textContent = 'Item ' + i;
  fragment.appendChild(div);
}
document.body.appendChild(fragment);

常见问题

  • Q: 如何高效地遍历DOM节点?
  • A: 使用NodeList.forEach或转换为数组后再使用Array.prototype.forEach

总结与展望

DOM节点操作是前端开发中不可或缺的一部分,它让JS能够直接与网页内容进行交互,实现复杂的动态功能。然而,为了保证良好的用户体验,开发者需要关注DOM操作的性能和效率,采取适当的优化策略。随着Web技术的发展,未来的DOM操作将更加高效、智能,为Web应用带来无限可能。

希望本文能够为你在前端开发旅程中提供坚实的理论基础和实用的操作技巧,让我们一起期待JS与DOM在未来的表现,继续探索和创新,推动Web开发向前发展。

一个HTML文档都会被浏览器解析转化出一个Dom树,Dom树中的每一项根据DOM模型解析为树形结构中一个个的节点,程序员就可以通过JavaScript语言动态操作每一个节点,此节主要了解掌握一些有关节点的知识和使用方法

之前说过使用document的方法可以快速获取元素节点如下:

1 快速获取HTML中的节点(主要是元素节点)

1.1 document.getElementById()根据元素的Id获得指定对象

1.2 document.getElementsByName()根据元素的name属性获得对象

1.3 document.getElementsByTagName()根据指定的标签名称获得其元素数组

1.4 document.getElementsByClassName()获取所有指定类名的元素数组

具体的使用方式在240章节的快速获取页面元素里面已经说过不再赘述

在一个HTML网页的Dom树中会有很多的节点,当操作具体的节点时,可以通过节点属性的方式快速便捷获取指定节点进行增删改查等操作

2 通过节点的属性获取相关的节点

通过此方法获取的节点不一定是元素节点,还有其他类型的节点,比如空文本节点

2.1 获取当前节点的父节点 parentNode

每一个节点都有一个parentNode属性用于获取当前节点(多为获取当前元素节点)的父节点,如果不存在,则返回null

获取当前节点的父节点方式为:当前节点.parentNode;如果想获取其"爷爷"辈的节点只能在其后面再加个点parentNode,再往上再加以此类推

获取父节点

通过document.getElementById("UList").parentNode 的方法获取到列表的父节点为body元素节点

2.2 获取当前节点的子级节点 childNodes

获取当前节点的子级节点,childNodes只获取当前节点的第一层子节点,是一个只读的数组NodeList对象即节点对象的数组,可以通过循环遍历其子节点

获取方式 当前节点.childNodes 注意:获取的节点中会有空文本节点

获取子级节点

通过IE浏览器可以查看其空文本节点

以下几种方式获取的节点有可能是空文本节点

2.3firstChild与lastChild

获取当前节点子级节点的第一个(childNodes[0])或最后一个的节点(childNodes[length-1])

获取当前节点下的首尾节点


2.4 nextSibling

· 获取当前节点的下一个兄弟节点

2.5 previousSibling

获取当前节点的上一个兄弟节点

获取上下兄弟节点