
JavaScript 的 DOM 操作
JavaScript 的 DOM 操作
什么是 DOM?
想象一下你的一个 HTML 网页文件。它里面有很多标签,比如 <html>
, <body>
, <h1>
, <p>
, <div>
等等。这些标签不是孤立的,它们之间有层级关系,比如 <h1>
在 <body>
里面,<body>
在 <html>
里面。
DOM (Document Object Model,文档对象模型) 就是浏览器为这个 HTML 文档在内存中创建的一个树形结构。它把整个文档的每一个部分(元素、属性、文本等)都看作是一个“对象”或“节点”。
通过 JavaScript,我们可以访问和操作这个树形结构中的任何一个节点,从而动态地改变网页的内容、结构和样式。简单来说:
DOM 是连接 HTML 页面和 JavaScript 语言的一座桥梁。
JavaScript 对网页的所有修改,实际上都是通过修改 DOM 树的节点来完成的。当 DOM 树被修改后,浏览器会自动重新渲染页面,向用户展示更新后的内容。
第一步:获取(选中)DOM 元素
要操作一个元素,首先你得能找到它。这就像你想跟某人说话,你得先知道他在哪里。JavaScript 提供了多种方法来“选中”页面上的元素。
假设我们有以下 HTML 代码:
<!DOCTYPE html>
<html>
<head>
<title>DOM 学习</title>
</head>
<body>
<h1 id="main-title">欢迎学习 DOM</h1>
<p class="content">这是一个段落。</p>
<p class="content">这是另一个段落。</p>
<div>
<a href="#">链接1</a>
<a href="#">链接2</a>
</div>
</body>
</html>
1. 通过 ID 获取 (最常用,最快)
ID 在一个页面中应该是唯一的。这是选中特定元素最精确、最高效的方法。
- 方法:
document.getElementById('你的ID')
- 返回: 一个单独的元素对象。如果找不到,返回
null
。
// 选中 ID 为 main-title 的 h1 元素
const titleElement = document.getElementById('main-title');
console.log(titleElement); // 会输出 <h1>...</h1> 这个元素对象
2. 通过 Class 名称获取
一个页面中可以有很多元素使用相同的 class。这个方法会把所有符合条件的元素都找出来。
- 方法:
document.getElementsByClassName('你的Class名')
- 返回: 一个 HTMLCollection (HTML集合),它像一个数组,包含了所有匹配的元素。
// 选中所有 class 为 content 的元素
const contentParagraphs = document.getElementsByClassName('content');
console.log(contentParagraphs); // 会输出一个包含两个 <p> 元素的 HTMLCollection
console.log(contentParagraphs[0]); // 可以像数组一样访问第一个 <p>
console.log(contentParagraphs[1]); // 访问第二个 <p>
3. 通过标签名 (Tag Name) 获取
这会选中页面上所有指定类型的标签。
- 方法:
document.getElementsByTagName('标签名')
- 返回: 一个 HTMLCollection。
// 选中所有的 <a> 标签
const allLinks = document.getElementsByTagName('a');
console.log(allLinks); // 输出包含两个 <a> 元素的 HTMLCollection
4. 通过 CSS 选择器获取 (现代、强大且灵活)
这是现代 JavaScript 中最推荐的方法,因为它像写 CSS 一样方便,几乎可以选中任何你想要的元素。
a) 选中第一个匹配的元素
- 方法:
document.querySelector('你的CSS选择器')
- 返回: 匹配到的第一个元素对象。如果找不到,返回
null
。
// 通过 ID 选择器
const title = document.querySelector('#main-title');
// 通过 class 选择器 (只会选中第一个)
const firstContent = document.querySelector('.content');
// 通过标签选择器
const firstLink = document.querySelector('a');
// 通过更复杂的后代选择器
const firstLinkInDiv = document.querySelector('div a');
b) 选中所有匹配的元素
- 方法:
document.querySelectorAll('你的CSS选择器')
- 返回: 一个 NodeList (节点列表),它也像一个数组,包含了所有匹配的元素。
// 选中所有 class 为 content 的段落
const allContents = document.querySelectorAll('.content');
// 选中 div 里的所有 a 标签
const allLinksInDiv = document.querySelectorAll('div a');
// 遍历所有选中的元素
allLinksInDiv.forEach(function(link) {
console.log(link); // 会依次打印出每个 <a> 元素
});
小结:
- 要精确选中一个元素,用
getElementById
或querySelector
。- 要选中一组元素,用
getElementsByClassName
,getElementsByTagName
或querySelectorAll
。querySelector
和querySelectorAll
是最现代和灵活的方法,建议优先使用。
第二步:修改 DOM 元素
一旦你用上面的方法选中了元素并存到了一个变量里,你就可以开始对它为所欲为了。
1. 修改元素内容
innerHTML
: 获取或设置一个元素内部的 HTML 内容。textContent
: 获取或设置一个元素内部的 纯文本内容。
const titleElement = document.getElementById('main-title');
// 读取内容
console.log(titleElement.innerHTML); // 输出 "欢迎学习 DOM"
console.log(titleElement.textContent); // 输出 "欢迎学习 DOM"
// 修改内容
// titleElement.innerHTML = '<i>JavaScript</i> DOM 操作'; // <i> 标签会被解析
titleElement.textContent = 'JavaScript DOM 操作'; // 更安全、高效,不会解析 HTML 标签
安全提示: 尽量使用
textContent
。如果你使用innerHTML
来插入用户提供的内容,可能会导致 XSS (跨站脚本) 攻击,因为恶意用户可能会输入<script>
标签来执行危险代码。
2. 修改元素属性
比如修改图片的 src
、链接的 href
等。
- 直接访问属性:
元素.属性名
(例如img.src
) - 通用方法:
元素.getAttribute('属性名')
和元素.setAttribute('属性名', '新值')
const link = document.querySelector('a'); // 选中第一个 a 标签
// 读取 href 属性
console.log(link.href);
// 修改 href 属性
link.setAttribute('href', 'https://www.google.com');
link.textContent = '前往 Google'; // 把文字也改一下
3. 修改元素样式 (CSS)
你可以直接修改元素的行内样式。
- 方法:
元素.style.样式属性 = '值'
注意: CSS 属性名在 JavaScript 中需要写成驼峰式命名 (camelCase)。例如 background-color
要写成 backgroundColor
,font-size
要写成 fontSize
。
const titleElement = document.getElementById('main-title');
// 修改样式
titleElement.style.color = 'blue';
titleElement.style.backgroundColor = '#f0f0f0'; // CSS 的 background-color
titleElement.style.fontSize = '32px'; // CSS 的 font-size
titleElement.style.padding = '10px';
4. 修改元素的 Class
动态地添加或移除 class 是控制元素样式的最佳实践(比直接修改 style
更好)。
- 方法:
元素.classList
,它提供了一些方便的方法:add('className')
: 添加一个 class。remove('className')
: 移除一个 class。toggle('className')
: 如果 class 存在则移除,不存在则添加。contains('className')
: 检查是否存在某个 class,返回true
或false
。
// 假设 CSS 文件里有一个 .highlight 类
// .highlight { color: red; font-weight: bold; }
const p = document.querySelector('.content');
// 添加 class
p.classList.add('highlight');
// 移除 class
// p.classList.remove('content');
// 切换 class (如果已有 highlight 就移除,没有就加上)
p.classList.toggle('highlight');
第三步:创建、添加和删除元素
这部分是让你的网页“活”起来的关键,你可以根据需要动态地增加或减少页面内容。
1. 创建新元素
首先,我们需要在 JavaScript 的“世界”里(内存中)创建一个新的 HTML 元素。这个元素被创建后,还不在页面上,像一个还没登场的演员。
- 方法:
document.createElement('标签名')
// 创建一个新的 <div> 元素
const newDiv = document.createElement('div');
// 创建一个新的 <img> 元素
const newImage = document.createElement('img');
// 创建一个新的列表项 <li>
const newItem = document.createElement('li');
创建好元素后,你可以像操作普通元素一样,给它添加内容、样式或属性。
// 给新创建的 li 添加文本内容
newItem.textContent = '我是新来的列表项';
// 给它添加一个 class
newItem.classList.add('list-item');
// 给新创建的图片设置 src 和 alt 属性
newImage.src = 'https://via.placeholder.com/150'; // 使用一个占位图
newImage.alt = '占位图片';
2. 添加元素到页面中
演员准备好了,现在要让他登台。你需要指定一个“父元素”(舞台),然后把新创建的元素添加进去。
a) 添加到父元素的末尾 (最常用)
- 现代方法:
父元素.append(新元素)
- 传统方法:
父元素.appendChild(新元素)
append()
更现代,功能也更强大(比如可以一次添加多个元素),推荐使用。
// 假设页面上已经有一个 <ul> 元素
// <ul id="my-list"><li>列表项1</li></ul>
// 1. 先选中父元素
const list = document.querySelector('#my-list');
// 2. 将我们上面创建的 newItem 添加进去
list.append(newItem);
执行后,HTML 就会变成:
<ul id="my-list">
<li>列表项1</li>
<li class="list-item">我是新来的列表项</li> </ul>
b) 添加到父元素的开头
- 现代方法:
父元素.prepend(新元素)
const list = document.querySelector('#my-list');
list.prepend(newItem); // newItem 会被加到列表项1的前面
3. 删除元素
当某个元素不再需要时,我们可以将它从 DOM 树中移除。
- 现代方法 (极其简单):
要删除的元素.remove()
这是最直接、最方便的方式。
// 假设我们要删除刚才添加的 newItem
// 首先,你需要能选中它,如果之前没有存到变量里的话
const itemToRemove = document.querySelector('.list-item'); // 假设我们这样能选中它
// 直接调用 remove()
if (itemToRemove) { // 最好先判断一下元素是否存在
itemToRemove.remove();
}
- 传统方法:
父元素.removeChild(要删除的子元素)
这个方法需要先获取到父元素,比较繁琐。
const parentList = itemToRemove.parentElement; // 先找到它的父元素
parentList.removeChild(itemToRemove); // 再通过父元素来删除它
显然,直接使用 .remove()
要简单得多。
第四步:响应用户交互 (事件处理)
静态的页面是不够的,我们需要对用户的行为(如点击、滚动、按键等)做出反应。这些行为在 JavaScript 中被称为 事件 (Events)。
我们可以为元素“绑定”一个 事件监听器 (Event Listener),它会一直“监听”某个特定事件,一旦事件发生,就执行我们预先定义好的函数。
1. 如何监听事件
- 核心方法:
元素.addEventListener('事件类型', '要执行的函数')
这是处理事件的标准方式,非常强大。
事件类型
: 一个字符串,表示你想监听哪种事件。常用事件有:click
: 用户单击。mouseover
: 鼠标指针移入元素。mouseout
: 鼠标指针移出元素。keydown
: 用户按下键盘上的任意键。keyup
: 用户释放键盘上的按键。submit
: 用户提交表单。
要执行的函数
: 也称为回调函数 (Callback Function) 或 事件处理器 (Event Handler)。当事件发生时,这个函数就会被自动调用。
2. click
事件示例
我们来做一个最经典的例子:点击一个按钮,然后改变页面上的一些文字。
<button id="my-button">点我!</button>
<p id="status-text">请点击按钮。</p>
// 1. 选中需要操作的元素
const btn = document.getElementById('my-button');
const statusText = document.getElementById('status-text');
// 2. 为按钮添加一个点击事件监听器
btn.addEventListener('click', function() {
// 这个匿名函数里的代码,只有在按钮被点击时才会执行
console.log('按钮被点击了!');
statusText.textContent = '恭喜!你成功触发了事件!';
statusText.style.color = 'green';
});
现在,每次你点击这个按钮,<p>
标签里的文字和颜色都会改变。
3. 事件对象 (Event Object)
当事件发生时,浏览器会自动创建一个包含该事件所有信息的事件对象,并把它作为第一个参数传递给你的回调函数。我们通常用 event
、evt
或 e
来命名这个参数。
这个对象非常有用,它包含了比如“是谁触发了事件”、“鼠标点击的位置”等信息。
event.target
: 这是事件对象中最重要的属性之一,它指向真正触发事件的那个元素。
我们来看一个例子,当鼠标悬浮在不同的列表项上时,高亮显示该列表项。
HTML:
<ul id="color-list">
<li>红色</li>
<li>绿色</li>
<li>蓝色</li>
</ul>
JavaScript:
const colorList = document.getElementById('color-list');
// 我们把事件监听器绑定在整个 <ul> 上,而不是每个 <li>
colorList.addEventListener('mouseover', function(event) {
// event.target 就是当前鼠标所在的那个 <li>
const targetLi = event.target;
// 确保我们操作的是 li 元素,而不是 ul 本身
if (targetLi.tagName === 'LI') {
targetLi.style.backgroundColor = 'yellow';
}
});
// 监听鼠标移出事件,用于恢复背景色
colorList.addEventListener('mouseout', function(event) {
if (event.target.tagName === 'LI') {
event.target.style.backgroundColor = ''; // 恢复默认背景
}
});
这种将事件监听器绑定在父元素上,利用 event.target
来管理子元素事件的技术,被称为事件委托 (Event Delegation),是一种非常高效的模式。
event.preventDefault()
: 这个方法可以阻止事件的默认行为。例如,阻止点击一个链接后跳转页面,或者阻止提交一个表单后刷新页面。
const myLink = document.querySelector('a'); // 假设页面有个链接
myLink.addEventListener('click', function(event) {
// 阻止链接的默认跳转行为
event.preventDefault();
console.log('链接跳转被我阻止了!');
});
通过掌握元素的增删改查和事件处理,你就具备了用 JavaScript 彻底掌控一个网页的能力,可以创造出丰富、动态、高交互性的用户体验。