当前位置: 首页 > article >正文

通俗易懂的 JS DOM 操作指南:从创建到挂载

目录

🧩 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 操作演示 &copy; 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>

http://www.lryc.cn/news/2395547.html

相关文章:

  • CSS Day07
  • 爬虫框架:scrapy使用心得
  • RV1126-OPENCV 交叉编译
  • 【深度学习】 19. 生成模型:Diffusion Models
  • JMeter 直连数据库
  • 易路 iBuilder:解构企业 AI 落地困境,重构智能体时代生产力范式
  • 数据库,Spring Boot,数据源
  • Linux 第三阶段课程:数据库基础与 SQL 应用
  • 计算机网络之路由表更新
  • 万兴PDF手机版
  • Qt -使用OpenCV得到SDF
  • Python 中Vector类的格式化实现,重点拆解其超球面坐标系的设计精髓
  • DDR5 ECC详细原理介绍与基于协议讲解
  • Linux系统之gettext详解
  • 基于Qt封装数据库基本增删改查操作,支持多线程,并实现SQLite数据库单例访问
  • EC800X QuecDuino开发板介绍
  • ARM P15协处理器指令详解:架构、编程与应用实践
  • PHP轻量级聊天室源码(源码下载)
  • MySQL数据表添加字段(三种方式)
  • leetcode hot100刷题日记——33.二叉树的层序遍历
  • 2、PyTorch基础教程:从张量到神经网络训练
  • 《数据结构初阶》【番外篇:快速排序的前世今生】
  • 【笔记】基于 MSYS2(MINGW64)的 Poetry 虚拟环境创建指南
  • PINNs案例——二维磁场计算
  • Hive SQL 中 BY 系列关键字全解析:从排序、分发到分组的核心用法
  • 数据类型检测有哪些方式?
  • 算法打开13天
  • Freeqwq 世界首个免费无限制 分布式 AI 算力平台 https://qwq.aigpu.cn/
  • 广告拦截器:全方位拦截,畅享无广告体验
  • .net Avalonia应用程序生命周期