DOM (文档对象模型)
你可以把网页想象成一棵树,HTML 是树的根,<html>、<head>、<body> 是它的主要分支,而每一个标签(如 <p>, <div>, <span>, <a>)都是一个节点或树叶。
JavaScript 可以通过这棵“树”来找到任何一个你想要的“树叶”(元素),然后读取它的信息(如文本内容、属性值、样式等)或修改它。
获取单个元素
当你只想找一个特定的元素时,可以使用以下方法。
getElementById()
这是最快、最直接的方法,但前提是元素必须有唯一的 id 属性。
<div id="main-title">欢迎来到我的网站</div>
<script>
// 通过ID获取元素
const titleElement = document.getElementById('main-title');
// 获取元素的文本内容
const titleText = titleElement.textContent; // 或 innerText
console.log(titleText); // 输出: "欢迎来到我的网站"
// 获取元素的标签名
const tagName = titleElement.tagName;
console.log(tagName); // 输出: "DIV"
</script>
querySelector()
这是一个非常强大和现代的方法,它使用 CSS 选择器 来查找元素,你可以用它通过 id、class、标签名或任何复杂的 CSS 选择器来找到第一个匹配的元素。
<p class="highlight">这是一个重要的段落。</p>
<a href="https://example.com">这是一个链接</a>
<script>
// 通过 class 选择器 (注意加点 .)
const highlightedPara = document.querySelector('.highlight');
console.log(highlightedPara.textContent); // 输出: "这是一个重要的段落。"
// 通过标签名选择器
const firstLink = document.querySelector('a');
console.log(firstLink.href); // 输出: "https://example.com"
// 通过属性选择器
const linkWithHref = document.querySelector('a[href]');
console.log(linkWithHref.textContent); // 输出: "这是一个链接"
</script>
获取多个元素
当你需要获取一组符合某个条件的元素时(所有的 <p> 标签或所有 class="item" 的元素),可以使用以下方法,这些方法返回的是一个 NodeList(类数组对象),你可以像数组一样遍历它。
getElementsByClassName()
根据 class 名获取元素集合。
<div class="item">项目 1</div>
<div class="item">项目 2</div>
<div class="item">项目 3</div>
<script>
// 获取所有 class 为 "item" 的元素
const items = document.getElementsByClassName('item');
// items 是一个 HTMLCollection,可以像数组一样遍历
for (let i = 0; i < items.length; i++) {
console.log(items[i].textContent);
}
// 或者使用 for...of 循环 (更推荐)
for (const item of items) {
console.log(item.textContent);
}
</script>
getElementsByTagName()
根据标签名获取元素集合。
<p>第一段文本。</p>
<p>第二段文本。</p>
<script>
// 获取所有的 <p> 标签
const paragraphs = document.getElementsByTagName('p');
for (const p of paragraphs) {
console.log(p.textContent);
}
</script>
querySelectorAll()
这是最灵活、最常用的获取多个元素的方法,它也使用 CSS 选择器,但会返回一个 静态的 NodeList,包含所有匹配的元素。
<ul>
<li class="fruit">苹果</li>
<li class="vegetable">胡萝卜</li>
<li class="fruit">香蕉</li>
</ul>
<script>
// 获取所有 class 为 "fruit" 的元素
const fruits = document.querySelectorAll('.fruit');
// 遍历并打印
fruits.forEach(fruit => {
console.log(fruit.textContent); // 输出 "苹果" 和 "香蕉"
});
// 获取所有的 <li> 标签
const allListItems = document.querySelectorAll('li');
console.log(allListItems.length); // 输出 3
</script>
获取元素的详细信息
找到元素之后,你通常还想获取它的具体信息。
获取文本内容
element.textContent: 获取元素及其所有后代的(不包含 HTML 标签)。element.innerText: 获取元素渲染后的可见文本内容(会考虑 CSS 的display和visibility属性)。- 推荐使用
textContent,因为它性能更好,并且不会受到 CSS 样式的影响。
- 推荐使用
<div id="info-box">你好,<strong>世界</strong>!</div>
<script>
const infoBox = document.getElementById('info-box');
console.log(infoBox.textContent); // 输出: "你好,世界!"
console.log(infoBox.innerText); // 输出: "你好,世界!"
</script>
获取和修改 HTML
element.innerHTML: 获取或设置元素内部的 HTML 代码。使用时要小心,如果内容来自用户输入,可能会引发 XSS (跨站脚本) 攻击。
<div id="container"></div>
<script>
const container = document.getElementById('container');
// 设置 HTML
container.innerHTML = '<p>这是一个新段落。</p><a href="#">一个链接</a>';
// 获取 HTML
console.log(container.innerHTML);
// 输出: <p>这是一个新段落。</p><a href="#">一个链接</a>
</script>
获取和修改属性
element.getAttribute('attribute-name'): 获取指定属性的值。element.setAttribute('attribute-name', 'new-value'): 设置指定属性的值。element.hasAttribute('attribute-name'): 检查是否存在某个属性。element.removeAttribute('attribute-name'): 移除某个属性。element.property(快捷方式): 对于标准 HTML 属性(如id,href,src,value),也可以直接通过 JS 属性访问。
<a id="my-link" href="https://old-site.com" target="_blank">旧链接</a>
<script>
const link = document.getElementById('my-link');
// 获取属性
console.log(link.getAttribute('href')); // 输出: "https://old-site.com"
console.log(link.href); // 输出: "https://old-site.com" (快捷方式)
// 修改属性
link.setAttribute('href', 'https://new-site.com');
console.log(link.href); // 输出: "https://new-site.com"
// 修改 data-* 属性 (自定义数据属性)
link.setAttribute('data-info', '这是一个重要的链接');
console.log(link.getAttribute('data-info')); // 输出: "这是一个重要的链接"
</script>
获取和修改样式
element.style.propertyName: 修改元素的内联样式(CSS 属性名需要转换为驼峰式,如background-color->backgroundColor)。window.getComputedStyle(element): 获取元素最终计算出的所有样式(包括继承来的和通过 CSS 文件设置的)。
<p id="styled-text">这段文字会被修改样式。</p>
<script>
const textElement = document.getElementById('styled-text');
// 修改内联样式
textElement.style.color = 'blue';
textElement.style.fontSize = '20px';
textElement.style.fontWeight = 'bold';
// 获取计算后的样式
const computedStyles = window.getComputedStyle(textElement);
console.log(computedStyles.color); // 输出类似 "rgb(0, 0, 255)"
console.log(computedStyles.fontSize); // 输出 "20px"
</script>
获取元素的层级关系
有时你需要根据元素在页面中的位置来找到它。
<div id="parent">
<p id="child1">子元素 1</p>
<p id="child2">子元素 2</p>
</div>
<script>
const parent = document.getElementById('parent');
const child1 = document.getElementById('child1');
// 获取父元素
console.log(child1.parentNode); // 或 child1.parentElement
// 输出: <div id="parent">...</div>
// 获取子元素列表 (HTMLCollection)
console.log(parent.children);
// 输出: [<p id="child1">...</p>, <p id="child2">...</p>]
// 获取第一个/最后一个子元素
console.log(parent.firstElementChild.textContent); // 输出: "子元素 1"
console.log(parent.lastElementChild.textContent); // 输出: "子元素 2"
// 获取下一个/上一个兄弟元素
console.log(child1.nextElementSibling.textContent); // 输出: "子元素 2"
console.log(child2.previousElementSibling.textContent); // 输出: "子元素 1"
</script>
高级应用:从外部 API 获取信息并展示到网页
这通常被称为“获取数据”或“AJAX/Fetch”,这是一个非常常见的场景,即从服务器获取数据,然后用 JavaScript 将其动态地插入到网页中。
示例:从 JSONPlaceholder (一个免费的测试API) 获取待办事项列表并显示。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">获取外部信息</title>
<style>
body { font-family: sans-serif; }
#todo-list { list-style: none; padding: 0; }
#todo-list li { background: #f4f4f4; margin: 5px 0; padding: 10px; border-radius: 3px; }
</style>
</head>
<body>
<h1>我的待办事项</h1>
<ul id="todo-list"></ul>
<script>
// 1. 找到要插入内容的容器
const todoListElement = document.getElementById('todo-list');
// 2. 使用 Fetch API 从服务器获取数据
fetch('https://jsonplaceholder.typicode.com/todos')
.then(response => {
// 检查响应是否成功
if (!response.ok) {
throw new Error('网络响应不正常');
}
// 将响应体解析为 JSON
return response.json();
})
.then(todos => {
// 3. 遍历获取到的数据,并创建 HTML 元素插入到页面中
todos.forEach(todo => {
// 创建一个 <li> 元素
const listItem = document.createElement('li');
// 设置 <li> 的文本内容
listItem.textContent = `${todo.id}: ${todo.title} (${todo.completed ? '已完成' : '未完成'})`;
// 将 <li> 添加到 <ul> 中
todoListElement.appendChild(listItem);
});
})
.catch(error => {
// 处理请求过程中可能发生的错误
console.error('获取数据时出错:', error);
todoListElement.textContent = '加载待办事项失败。';
});
</script>
</body>
</html>
总结与最佳实践
- 首选
querySelector和querySelectorAll:它们功能强大,语法统一(使用 CSS 选择器),能满足绝大多数需求。 - 明确目标:如果你确定要找的元素有唯一的
id,getElementById是最快的选择。 - 注意返回值类型:
getElementBy...返回的是HTMLCollection(动态的),而querySelectorAll返回的是NodeList(静态的),了解它们的区别有助于避免在遍历后修改 DOM 时出现问题。 - 安全第一:使用
innerHTML时,确保内容是可信的,以防止 XSS 攻击,对于动态内容,优先使用textContent或document.createElement+appendChild的方式。 - 从实践中学习:尝试在浏览器的开发者工具(按 F12 打开)的 "Console" 中直接运行这些代码,并观察 "Elements" 面板的变化,这是最快的学习方式。
