目录
🧩 1. 创建元素:document.createElement / createElementNS
📝 2. 创建文本:document.createTextNode
✏️ 3. 修改文本:node.nodeValue
🗑️ 4. 移除元素:el.removeChild()
📍 5. 精准插入:el.insertBefore()
➕ 6. 尾部追加:el.appendChild()
👨👦 7. 获取父元素:el.parentNode
👉 8. 获取兄弟元素:el.nextSibling
🌀 9. 挂载 Portal:document.querySelector
🌰 综合应用示例:动态列表操作
📚 核心知识点总结
DOM 演示操作 文档
理解 DOM 操作是前端开发的核心基础。下面我会用通俗的语言和实际场景,带你掌握这些关键 API 的使用技巧:
🧩 1. 创建元素:document.createElement
/ createElementNS
作用:创建 HTML 元素(标签)
区别:
createElement
:创建普通 HTML 元素
const div = document.createElement('div'); // 创建 <div>
const button = document.createElement('button'); // 创建 <button>
createElementNS
:创建带命名空间的元素(如 SVG)
// 创建 SVG 元素必须使用命名空间
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
📝 2. 创建文本:document.createTextNode
-
作用:创建纯文本节点(非 HTML)
-
场景:当需要插入纯文本时(避免 XSS 攻击)
const text = document.createTextNode('安全文本内容');
div.appendChild(text); // <div>安全文本内容</div>
✏️ 3. 修改文本:node.nodeValue
-
作用:修改文本节点的内容(注意:不适用于元素节点!)
-
正确用法:
const textNode = document.createTextNode('原始文本');
div.appendChild(textNode);
// 修改文本内容
textNode.nodeValue = '修改后的文本'; // div内容实时更新
🗑️ 4. 移除元素:el.removeChild()
-
作用:从父元素中移除指定的子元素
-
三步操作:
const parent = document.getElementById('parent');
const child = document.getElementById('child');
// 必须通过父元素执行移除
parent.removeChild(child);
📍 5. 精准插入:el.insertBefore()
-
作用:在指定子节点前插入新元素
-
参数顺序:
父元素.insertBefore(新元素, 参考元素)
const list = document.getElementById('list');
const newItem = document.createElement('li');
const thirdItem = list.children[2];
// 在第三个元素前插入
list.insertBefore(newItem, thirdItem);
➕ 6. 尾部追加:el.appendChild()
-
作用:在父元素末尾添加子元素
-
最常用操作:
const container = document.querySelector('.container');
const newCard = document.createElement('div');
container.appendChild(newCard); // 添加到container末尾
👨👦 7. 获取父元素:el.parentNode
-
作用:获取当前元素的直接父元素
-
典型场景:事件委托
button.addEventListener('click', (e) => {
// 点击按钮后获取其父元素
const parent = e.target.parentNode;
parent.style.backgroundColor = 'yellow';
});
;
👉 8. 获取兄弟元素:el.nextSibling
-
注意:返回下一个节点(可能是文本/注释/元素)
-
实际使用:通常配合
nodeType
过滤
const current = document.getElementById('item3');
let next = current.nextSibling;
// 跳过文本节点(如换行符)
while (next && next.nodeType !== 1) {
next = next.nextSibling;
}
console.log(next); // 得到下一个元素节点
🌀 9. 挂载 Portal:document.querySelector
-
特殊场景:渲染到 DOM 树之外的位置(如模态框)
// 在 body 末尾创建模态框容器
const modalRoot = document.createElement('div');
document.body.appendChild(modalRoot);
// 创建 Portal 内容
const modalContent = document.createElement('div');
modalContent.innerHTML = '<h2>登录窗口</h2>';
// 挂载到指定容器
const container = document.querySelector('#portal-root');
container.appendChild(modalContent);
🌰 综合应用示例:动态列表操作
<ul id="list">
<li>第一项</li>
<li>第二项</li>
</ul>
<button id="btn">添加项目</button>
<script>
const list = document.getElementById('list');
const btn = document.getElementById('btn');
btn.addEventListener('click', () => {
// 1. 创建元素
const newItem = document.createElement('li');
// 2. 创建文本(安全方式)
const text = document.createTextNode('新项目');
newItem.appendChild(text);
// 3. 在第二项前插入
const secondItem = list.querySelector('li:nth-child(2)');
list.insertBefore(newItem, secondItem);
// 4. 添加删除功能
newItem.onclick = function() {
this.parentNode.removeChild(this); // 通过父元素移除
};
});
</script>
📚 核心知识点总结
API | 作用 | 注意事项 |
---|---|---|
createElement | 创建 HTML 元素 | 区分普通元素和 SVG |
createTextNode | 创建安全文本节点 | 防止 XSS 攻击 |
nodeValue | 修改文本节点内容 | 对元素节点无效 |
removeChild | 父元素移除子元素 | 需通过父元素调用 |
insertBefore | 在指定位置插入元素 | 参数顺序:(新元素, 参考元素) |
appendChild | 末尾添加元素 | 最常用的添加方法 |
parentNode | 获取父元素 | 事件委托的关键 |
nextSibling | 获取下一个兄弟节点 | 可能包含文本节点 |
querySelector | 精确查找元素 | Portal 挂载的核心 |
💡 最佳实践提示:操作 DOM 时,尽量减少重排(reflow)次数。可通过创建文档片段(
DocumentFragment
)批量操作元素后再一次性添加到 DOM 树中。
掌握这些基础 API 后,你将能轻松应对大多数 DOM 操作需求,为学习现代前端框架打下坚实基础!
DOM 演示操作 文档
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DOM操作演示</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
color: #fff;
min-height: 100vh;
padding: 20px;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
text-align: center;
padding: 20px 0;
margin-bottom: 30px;
background: rgba(0, 0, 0, 0.3);
border-radius: 15px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(4px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
h1 {
font-size: 2.8rem;
margin-bottom: 10px;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
.subtitle {
font-size: 1.2rem;
opacity: 0.9;
max-width: 800px;
margin: 0 auto;
}
.content {
display: flex;
flex-wrap: wrap;
gap: 30px;
margin-bottom: 40px;
}
.demo-section {
flex: 1;
min-width: 300px;
background: rgba(0, 0, 0, 0.2);
border-radius: 15px;
padding: 25px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(4px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.section-title {
font-size: 1.8rem;
margin-bottom: 20px;
color: #ffcc00;
text-align: center;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-bottom: 25px;
}
.btn {
flex: 1;
min-width: 200px;
padding: 15px 20px;
background: linear-gradient(to right, #3498db, #2980b9);
color: white;
border: none;
border-radius: 50px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
.btn:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
background: linear-gradient(to right, #3cb0fd, #3498db);
}
.btn:active {
transform: translateY(1px);
}
.btn-remove {
background: linear-gradient(to right, #e74c3c, #c0392b);
}
.btn-remove:hover {
background: linear-gradient(to right, #ff6b6b, #e74c3c);
}
.btn-insert {
background: linear-gradient(to right, #2ecc71, #27ae60);
}
.btn-insert:hover {
background: linear-gradient(to right, #1dd1a1, #2ecc71);
}
.btn-info {
background: linear-gradient(to right, #9b59b6, #8e44ad);
}
.btn-info:hover {
background: linear-gradient(to right, #be2edd, #9b59b6);
}
.demo-area {
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
padding: 20px;
min-height: 150px;
margin-top: 20px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.code-section {
background: rgba(0, 0, 0, 0.3);
border-radius: 10px;
padding: 20px;
margin-top: 20px;
font-family: 'Courier New', monospace;
font-size: 0.95rem;
overflow-x: auto;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.dom-tree {
background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
padding: 15px;
margin-top: 15px;
font-family: monospace;
font-size: 0.9rem;
white-space: pre;
overflow-x: auto;
}
.explanation {
background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
padding: 20px;
margin-top: 20px;
border-left: 4px solid #3498db;
}
.explanation h3 {
color: #3498db;
margin-bottom: 10px;
}
.highlight {
background: rgba(255, 215, 0, 0.2);
padding: 2px 5px;
border-radius: 4px;
}
.counter {
text-align: center;
font-size: 1.2rem;
margin-top: 20px;
padding: 10px;
background: rgba(0, 0, 0, 0.3);
border-radius: 10px;
}
.element {
color: #ffcc00;
}
.text-node {
color: #1abc9c;
}
footer {
text-align: center;
padding: 20px;
margin-top: 30px;
background: rgba(0, 0, 0, 0.3);
border-radius: 15px;
}
@media (max-width: 768px) {
.content {
flex-direction: column;
}
.btn {
min-width: 100%;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>DOM 操作演示</h1>
<p class="subtitle">本演示展示了JavaScript中常用的DOM操作方法,包括创建元素、修改文本、插入节点、移除节点等操作。</p>
</header>
<div class="content">
<div class="demo-section">
<h2 class="section-title">文本节点操作</h2>
<div class="controls">
<button id="edit" class="btn">修改文字 (nodeValue)</button>
<button id="remove" class="btn btn-remove">移除文本节点 (removeChild)</button>
</div>
<div class="demo-area" id="text-demo">
<div id="app"></div>
</div>
<div class="code-section">
<pre><code>// 创建元素和文本节点
const heading = document.createElement('h1');
const textNode = document.createTextNode('hello world');
// 添加文本节点到元素
heading.appendChild(textNode);
// 添加元素到DOM
app.appendChild(heading);
// 修改文本
editBtn.addEventListener('click', () => {
textNode.nodeValue = 'hello vue';
});
// 移除文本节点
removeBtn.addEventListener('click', () => {
if (textNode.parentNode) {
heading.removeChild(textNode);
}
});</code></pre>
</div>
<div class="explanation">
<h3>说明</h3>
<p><span class="highlight">nodeValue</span> 属性用于获取或设置文本节点的内容。</p>
<p><span class="highlight">removeChild()</span> 方法从DOM中移除指定的子节点。</p>
</div>
</div>
<div class="demo-section">
<h2 class="section-title">节点插入操作</h2>
<div class="controls">
<button id="insertBefore" class="btn btn-insert">insertBefore (在指定节点前插入)</button>
<button id="insertBefore2" class="btn btn-insert">insertBefore (在末尾插入)</button>
<button id="parentNode" class="btn btn-info">显示父节点和兄弟节点</button>
</div>
<div class="demo-area">
<div id="parentDiv">
<h1 id="childElement">childElement (原始节点)</h1>
</div>
</div>
<div class="dom-tree" id="domTree">
<!-- DOM树结构将在这里显示 -->
</div>
<div class="code-section">
<pre><code>// 在指定节点前插入
insertBeforeBtn.addEventListener('click', () => {
const newNode = document.createElement("span");
newNode.textContent = '新插入的span (之前)';
newNode.className = 'new-node';
const parentDiv = childElement.parentNode;
parentDiv.insertBefore(newNode, childElement);
});
// 在末尾插入(相当于appendChild)
insertBefore2Btn.addEventListener('click', () => {
const newNode = document.createElement("span");
newNode.textContent = '新插入的span (末尾)';
newNode.className = 'new-node';
const parentDiv = childElement.parentNode;
parentDiv.insertBefore(newNode, null);
});
// 显示节点关系
parentNodeBtn.addEventListener('click', () => {
const parent = childElement.parentNode;
const nextSibling = childElement.nextSibling;
// 显示在DOM树区域
});</code></pre>
</div>
<div class="explanation">
<h3>说明</h3>
<p><span class="highlight">insertBefore()</span> 方法在参考节点之前插入一个节点。</p>
<p>如果参考节点为 <span class="highlight">null</span>,则新节点将插入到子节点列表的末尾。</p>
<p><span class="highlight">parentNode</span> 属性返回指定节点的父节点。</p>
<p><span class="highlight">nextSibling</span> 属性返回指定节点之后紧跟的节点。</p>
</div>
</div>
</div>
<div class="counter">
操作计数: <span id="operationCount">0</span>
</div>
<footer>
<p>DOM 操作演示 © 2023 | 通过本演示理解核心DOM操作</p>
</footer>
</div>
<script>
// 操作计数器
let operationCount = 0;
const operationCountElement = document.getElementById('operationCount');
// 更新操作计数
function updateCounter() {
operationCount++;
operationCountElement.textContent = operationCount;
}
// 第一部分:文本节点操作
const app = document.getElementById('app');
const heading = document.createElement('h1');
heading.className = 'element';
const textNode = document.createTextNode('hello world');
heading.appendChild(textNode);
app.appendChild(heading);
// 添加按钮事件
document.getElementById('edit').addEventListener('click', () => {
textNode.nodeValue = '文本已修改: hello vue!';
updateCounter();
});
document.getElementById('remove').addEventListener('click', () => {
if (textNode.parentNode) {
heading.removeChild(textNode);
updateCounter();
}
});
// 第二部分:节点插入操作
const childElement = document.getElementById('childElement');
document.getElementById('insertBefore').addEventListener('click', () => {
const newNode = document.createElement("span");
newNode.textContent = '新插入的span (在原始节点之前)';
newNode.className = 'new-node';
const parentDiv = childElement.parentNode;
parentDiv.insertBefore(newNode, childElement);
updateCounter();
updateDomTree();
});
document.getElementById('insertBefore2').addEventListener('click', () => {
const newNode = document.createElement("span");
newNode.textContent = '新插入的span (在父元素末尾)';
newNode.className = 'new-node';
const parentDiv = childElement.parentNode;
parentDiv.insertBefore(newNode, null);
updateCounter();
updateDomTree();
});
document.getElementById('parentNode').addEventListener('click', () => {
const parent = childElement.parentNode;
const nextSibling = childElement.nextSibling;
alert(`父节点ID: ${parent.id}\n下一个兄弟节点: ${nextSibling ? nextSibling.nodeName : '无'}`);
updateCounter();
});
// 更新DOM树显示
function updateDomTree() {
const parentDiv = document.getElementById('parentDiv');
const domTreeElement = document.getElementById('domTree');
// 简单的DOM树表示
let tree = `#${parentDiv.id}\n`;
tree += `├── ${parentDiv.firstChild.nodeName} (文本节点)\n`;
for (let i = 0; i < parentDiv.childNodes.length; i++) {
const node = parentDiv.childNodes[i];
if (node.nodeType === Node.ELEMENT_NODE) {
tree += `├── <${node.nodeName.toLowerCase()}>`;
if (node.id) tree += ` #${node.id}`;
if (node.className) tree += ` .${node.className}`;
if (node.textContent) tree += ` - "${node.textContent}"`;
tree += '\n';
}
}
domTreeElement.textContent = tree;
}
// 初始化DOM树显示
updateDomTree();
// 添加一些初始样式
const style = document.createElement('style');
style.textContent = `
.element { color: #ffcc00; }
.text-node { color: #1abc9c; }
.new-node {
display: block;
padding: 10px;
margin: 10px 0;
background: rgba(52, 152, 219, 0.2);
border: 1px dashed #3498db;
border-radius: 5px;
}
`;
document.head.appendChild(style);
</script>
</body>
</html>