什么是DOM?深入理解文档对象模型
【dom是啥】?DOM,全称是文档对象模型 (Document Object Model)。简单来说,它是浏览器将加载的HTML文档转换成一个结构化的、可以通过编程语言(主要是JavaScript)进行访问和操作的对象模型。
想象一下你写了一个HTML文件,它只是一堆文本。浏览器读取这个文本后,并不会直接在屏幕上画出像素,而是先在内存里构建一个这个HTML结构的内部表示。这个内部表示就是DOM。它把文档中的每一个部分(比如标签、文本、属性)都变成了一个个具体的对象,并且按照它们在HTML中的层级关系组织起来。
DOM不是HTML本身,也不是浏览器渲染出来的最终页面。 它是一个介于HTML文档和页面显示之间的抽象层,一个编程接口 (API)。通过这个接口,开发者可以动态地读取、修改、添加或删除页面上的任何元素、内容或属性。
为什么需要DOM?操作页面内容的桥梁
【为什么需要dom】?如果只有静态的HTML,我们的网页就只能展示信息,无法与用户互动,也无法在加载后根据用户行为或外部数据进行改变。DOM的存在,正是为了让静态的HTML文档“活”起来,变得可编程和动态化。
- 动态更新内容: 无需刷新整个页面,就能改变页面上的文字、图片或其他元素。比如点击一个按钮后,更新购物车里的商品数量。
- 响应用户操作: 检测用户的点击、鼠标移动、键盘输入等行为,并根据这些行为执行相应的操作。比如点击按钮弹出对话框。
- 改变页面结构: 在页面加载后,动态地添加新的元素(如列表项、段落)、删除现有元素或改变它们的父子关系。比如一个待办事项列表,用户每输入一项就动态添加一个列表项。
- 修改元素样式: 改变元素的颜色、大小、位置等样式属性,实现动态的视觉效果。比如鼠标悬停在一个元素上时改变它的背景色。
可以说,没有DOM,现代的、具有丰富交互性的Web应用就无从谈起。它提供了一套标准的、跨浏览器的方式来与网页内容打交道。
DOM在哪里?它存在于浏览器内存中
【dom在哪里】?DOM是浏览器在解析HTML文档时在计算机内存中创建的一个数据结构。
当你在浏览器地址栏输入一个网址并按下回车后:
- 浏览器发送请求获取HTML文件。
- 浏览器开始解析HTML文件,逐行读取其中的标签、文本等。
- 在解析过程中,浏览器会根据HTML的结构,在内存中构建对应的DOM树。同时,也会构建CSS对象模型 (CSSOM)。
- DOM树和CSSOM树结合,形成渲染树 (Render Tree)。
- 浏览器根据渲染树计算每个元素的位置和大小,最终将页面绘制在屏幕上。
这个DOM树就一直存在于浏览器进程的内存中,直到你关闭这个网页标签页或窗口。
因此,当你使用JavaScript代码操作DOM时,实际上是在与这个位于浏览器内存中的对象模型进行交互,而不是直接修改硬盘上的HTML文件。
DOM的结构是什么样的?一棵树!
【dom的结构】正如其名“文档对象模型”,它将整个HTML文档视为一个“文档对象”。这个文档对象内部又包含各种其他对象,并且它们之间通过父子、兄弟关系连接起来,形成一个类似家谱的层层嵌套的树形结构。
这棵树的“根”通常是Document
对象(代表整个文档),它下面是<html>
元素,<html>
下面有<head>
和<body>
等等,一直延伸到最具体的标签和文本。
DOM树中的主要节点类型:
-
文档节点 (Document Node): 代表整个HTML文档,是DOM树的入口点。通常通过全局的
document
对象来访问。 -
元素节点 (Element Node): 代表HTML标签,比如
<div>
、<p>
、<a>
、<img>
等。每个元素节点都可以有子节点(其他元素或文本)和属性。 -
文本节点 (Text Node): 代表HTML标签内的文本内容。比如
<p>这是一个文本段落</p>
中,“这是一个文本段落”就是一个文本节点。 -
属性节点 (Attribute Node): 代表HTML元素的属性,比如
<a href="...">
中的href="..."
。注意:属性节点在DOM树中通常不被视为独立的子节点,而是作为元素节点的属性来访问。 -
注释节点 (Comment Node): 代表HTML注释
<!-- ... -->
。
理解这个树形结构非常重要,因为它决定了你如何通过父子、兄弟关系来遍历和定位页面上的元素。
如何与DOM交互?使用JavaScript APIs
【如何与dom交互】与DOM进行交互的主要方式是使用JavaScript提供的DOM API (应用程序接口)。这些API是一组内置的对象、属性和方法,允许你像操作普通JavaScript对象一样操作DOM树中的节点。
最常用的交互场景包括:
- 获取DOM元素(节点): 找到页面上你想要操作的特定元素。
- 修改DOM元素: 改变元素的属性、内容、样式等。
- 添加或删除DOM元素: 改变页面的结构。
- 监听事件: 响应用户的交互。
怎么获取DOM元素?多种方法按需选择
【怎么获取dom元素】这是操作DOM的第一步。JavaScript提供了多种方法来根据不同的条件查找页面上的元素:
-
通过ID获取:
使用
document.getElementById('some-id')
。这是最直接和快速的方法,因为ID在文档中应该是唯一的。它返回单个元素对象,如果找不到则返回null
。示例:
const myElement = document.getElementById('header-title');
-
通过标签名获取:
使用
document.getElementsByTagName('tag-name')
。它返回一个包含所有指定标签名元素的HTMLCollection(一个类似数组的对象)。示例:
const paragraphs = document.getElementsByTagName('p'); // 获取页面上所有<p>标签
-
通过类名获取:
使用
document.getElementsByClassName('class-name')
。它返回一个包含所有指定类名元素的HTMLCollection。示例:
const errorMessages = document.getElementsByClassName('error'); // 获取所有class包含error的元素
-
通过CSS选择器获取(单个):
使用
document.querySelector('css-selector')
。这是非常强大的方法,可以使用任何CSS选择器来查找元素。它返回匹配到的第一个元素,如果找不到则返回null
。示例:
const firstLink = document.querySelector('a.external'); // 获取第一个class为external的<a>标签
-
通过CSS选择器获取(所有):
使用
document.querySelectorAll('css-selector')
。与querySelector
类似,但它返回一个包含所有匹配元素的NodeList(另一个类似数组的对象)。示例:
const allButtons = document.querySelectorAll('button:not(.disabled)'); // 获取所有非disabled状态的按钮
选择哪种方法取决于你想通过什么信息来定位元素(是ID、类、标签名还是更复杂的CSS规则)。现代开发中,querySelector
和querySelectorAll
因其灵活性而非常常用。
怎么修改DOM内容、属性和样式?
【怎么修改dom内容和结构】获取到元素对象后,就可以通过它的属性和方法来修改它:
修改内容:
-
element.textContent
: 获取或设置元素的文本内容,会忽略HTML标签。设置时,任何HTML标记都会被当作纯文本处理。示例:
myElement.textContent = '新的纯文本内容';
-
element.innerHTML
: 获取或设置元素的HTML内容。设置时,如果包含HTML标记,浏览器会解析并创建相应的DOM节点。示例:
myElement.innerHTML = '<strong>新的加粗文本</strong>';
使用
innerHTML
时需注意安全问题,避免插入来自不可信源的用户输入。
修改属性:
-
element.attributeName
: 对于一些标准属性(如id
,src
,href
,className
,value
等),可以直接作为元素对象的属性来访问和修改。示例:
const myImage = document.getElementById('product-img');
myImage.src = 'new-image.jpg';
myElement.className = 'highlight active'; // 直接设置或覆盖所有类名 -
element.setAttribute('name', 'value')
: 设置元素的任意属性。示例:
myElement.setAttribute('data-status', 'processed');
-
element.getAttribute('name')
: 获取属性值。 -
element.removeAttribute('name')
: 移除属性。
修改样式:
-
element.style.propertyName
: 直接通过元素的style
属性访问和修改元素的内联样式。属性名使用驼峰命名法(如backgroundColor
而不是background-color
)。示例:
myElement.style.color = 'red';
myElement.style.fontSize = '16px'; -
element.classList
: 这是一个非常有用的属性,用于方便地添加、移除或切换元素的CSS类。element.classList.add('class-name')
element.classList.remove('class-name')
element.classList.toggle('class-name')
element.classList.contains('class-name')
通过操作类名来改变样式是更推荐的方式,因为它将样式逻辑(CSS)与行为逻辑(JavaScript)分离。
示例:
myElement.classList.add('active');
myElement.classList.remove('hidden');
怎么添加或移除DOM元素?改变页面结构
【怎么添加或移除dom元素】除了修改现有元素,DOM API也允许我们动态地创建新元素并将它们插入到文档中,或者从文档中移除元素。
添加元素:
-
创建新元素: 使用
document.createElement('tag-name')
创建一个新的元素节点。示例:
const newParagraph = document.createElement('p');
-
创建文本节点(如果需要): 使用
document.createTextNode('text content')
创建一个文本节点。示例:
const textNode = document.createTextNode('这是一个新段落的文本。');
-
组装元素(可选): 将文本节点或其他子元素添加到新创建的元素中,使用
element.appendChild(childNode)
。示例:
newParagraph.appendChild(textNode);
-
将新元素插入到DOM树中: 找到一个现有的父元素,然后使用其方法将新元素添加为它的子节点。
parentNode.appendChild(newNode)
:将节点添加到父元素的子节点列表的末尾。parentNode.insertBefore(newNode, referenceNode)
:将节点插入到父元素的子节点列表中,放在指定参考节点之前。
示例:
const container = document.getElementById('content-area');
container.appendChild(newParagraph); // 将新段落添加到id为content-area的元素末尾
移除元素:
-
通过父节点移除子节点: 找到要移除元素的父节点,然后使用
parentNode.removeChild(childNode)
方法。示例:
const itemToRemove = document.getElementById('item-to-remove');
const parent = itemToRemove.parentNode;
parent.removeChild(itemToRemove); -
元素自移除(更常用): 现代浏览器支持
element.remove()
方法,可以直接让元素自己从其父节点中移除。示例:
const itemToRemove = document.getElementById('item-to-remove');
itemToRemove.remove();
操作DOM有什么影响?页面会重新渲染
【操作dom有什么影响】当你使用JavaScript改变了DOM树的结构、内容或元素的属性/样式时,浏览器会检测到这些变化。为了让用户看到最新的页面状态,浏览器会执行一个被称为重排 (Reflow) 或重绘 (Repaint) 的过程。
- 重排 (Reflow): 当你改变了元素的布局、几何属性(如宽度、高度、边距、位置)或添加/删除元素时,浏览器需要重新计算页面中所有(或部分)元素的位置和大小,这个过程叫做重排。重排是一个比较耗性能的操作,因为它可能影响到其他元素甚至整个文档的布局。
- 重绘 (Repaint): 当你改变了元素的非布局属性,只影响元素的可见外观(如颜色、背景色、透明度),而不会影响其布局时,浏览器只需要重新绘制受影响的元素,这个过程叫做重绘。重绘通常比重排性能开销小。
浏览器会尽量优化这个过程,比如批量处理DOM修改,但频繁或大量的DOM操作仍然是导致网页性能问题的常见原因。因此,在进行复杂的DOM操作时,开发者通常会考虑一些优化技巧,比如批量更新、使用文档碎片(DocumentFragment)或者现代框架(如React、Vue)的虚拟DOM机制。
总结
总而言之,【dom是啥】?DOM是浏览器为HTML文档创建的一个内存中的对象模型,它将文档结构化为一棵树,并通过JavaScript API提供了强大的能力,让开发者可以动态地访问、修改和控制网页的每一个部分。理解DOM的结构、它与HTML的区别以及如何通过JavaScript获取和操作元素,是进行网页动态开发和交互的基础。它存在于浏览器内存中,通过操作DOM,我们可以实现响应用户输入、动态加载内容、改变页面样式等丰富的Web功能,而这些操作最终会触发浏览器的渲染更新,呈现在用户眼前。