引言:
DOM 操作是 JavaScript 控制网页动态交互的核心能力,涵盖元素选择、内容与样式修改、结构增删、事件处理及表单操作等完整体系。本文系统讲解 DOM 树结构及常用 API 的使用方法。
JavaScript DOM 操作详解
当你使用 JavaScript 操作网页时,最核心的能力就是与 DOM(Document Object Model,文档对象模型) 进行交互。DOM 是浏览器将 HTML 文档解析后生成的一个树状结构 ,它将网页中的每一个元素、属性、文本都抽象为"节点"(Node)。有了 DOM,JavaScript 就可以动态地读取、修改、添加或删除页面上的任何内容。
一、什么是 DOM?
当浏览器加载一个 HTML 页面时,它会解析 HTML 代码,并构建一个 DOM 树。这个树形结构清晰地反映了 HTML 元素的嵌套关系。
例如,对于下面的 HTML 代码:
1 2 3 4 5 6 7 8 9 10 11 12 <!DOCTYPE html > <html > <head > <title > 我的页面</title > </head > <body > <div id ="main" > <h1 > 欢迎</h1 > <p class ="intro" > 这是一段介绍文字。</p > </div > </body > </html >
浏览器会生成如下的 DOM 树结构:
1 2 3 4 5 6 7 8 9 10 11 Document └── html ├── head │ └── title │ └── "我的页面" └── body └── div#main ├── h1 │ └── "欢迎" └── p.intro └── "这是一段介绍文字。"
JavaScript 通过 DOM 提供的 API,可以轻松地遍历、查询和操作这棵树中的任意一个节点。
二、获取 DOM 元素
在对 DOM 元素进行操作之前,首先需要获取到它。JavaScript 提供了多种元素选择方法。
1. getElementById
通过元素的 id 属性获取,返回匹配的元素。
1 2 let element = document .getElementById ('header' );
2. getElementsByClassName
通过元素的 class 属性获取,返回一个类数组对象 (HTMLCollection)。注意,即使只有一个元素,也要用索引来访问。
1 2 3 let elements = document .getElementsByClassName ('intro' );let firstElement = elements[0 ];
3. getElementsByTagName
通过元素标签名获取,返回一个类数组对象(HTMLCollection)。
1 2 3 let paragraphs = document .getElementsByTagName ('p' );let firstParagraph = paragraphs[0 ];
4. querySelector
使用 CSS 选择器 获取匹配的第一个 元素。这是最灵活、最推荐使用的选择方法。
1 2 3 4 5 6 7 8 let header = document .querySelector ('#header' );let intro = document .querySelector ('.intro' );let mainDiv = document .querySelector ('div.main-content' );
5. querySelectorAll
使用 CSS 选择器获取所有 匹配的元素,返回一个 NodeList (节点列表)。NodeList 与 HTMLCollection 类似,但支持 forEach 等数组方法。
1 2 3 4 5 6 let items = document .querySelectorAll ('.list-item' );items.forEach (function (item ) { console .log (item.textContent ); });
6. 特殊的选择方法
1 2 3 4 5 6 7 8 let root = document .documentElement ;let head = document .head ;let body = document .body ;
三、操作元素内容
1. innerHTML
获取或设置元素内部的 HTML 内容 。它会解析字符串中的 HTML 标签。
1 2 3 4 5 6 7 let div = document .querySelector ('#container' );console .log (div.innerHTML );div.innerHTML = '<h2>新标题</h2><p>这是一段新内容。</p>' ;
2. textContent
获取或设置元素内部的纯文本内容 ,不会解析 HTML 标签。
1 2 3 4 5 6 7 let div = document .querySelector ('#container' );console .log (div.textContent );div.textContent = '这是一段纯文本内容。' ;
3. innerText
与 textContent 类似,但会考虑 CSS 样式(如隐藏元素的内容不会返回),性能略低于 textContent。
四、操作元素属性
1. 标准属性的读写
1 2 3 4 5 6 7 8 9 let img = document .querySelector ('#avatar' );let src = img.getAttribute ('src' );let alt = img.alt ; img.setAttribute ('src' , 'new-image.jpg' ); img.alt = '新的头像' ;
2. 操作 class 属性
1 2 3 4 5 6 7 8 9 10 11 12 13 let element = document .querySelector ('#box' );console .log (element.className );element.className = 'new-class' ; element.classList .add ('active' ); element.classList .remove ('hidden' ); element.classList .toggle ('open' ); element.classList .contains ('active' );
3. 操作 style 属性(内联样式)
1 2 3 4 5 6 7 8 let element = document .querySelector ('#box' );element.style .color = 'red' ; element.style .fontSize = '20px' ; element.style .cssText = 'color: blue; background-color: yellow;' ;
五、操作元素结构
1. 创建新元素
使用 createElement 创建新元素,使用 createTextNode 创建文本节点。
1 2 3 4 5 6 7 8 let newItem = document .createElement ('li' );let text = document .createTextNode ('新项目' );newItem.appendChild (text);
2. 添加子元素
1 2 3 4 5 6 7 8 let list = document .querySelector ('#myList' );list.appendChild (newItem); let firstItem = list.children [0 ];list.insertBefore (newItem, firstItem);
3. 删除子元素
1 2 3 4 5 6 7 8 let list = document .querySelector ('#myList' );let firstItem = list.children [0 ];list.removeChild (firstItem); firstItem.remove ();
4. 替换子元素
1 2 3 4 5 6 7 let list = document .querySelector ('#myList' );let oldItem = list.children [0 ];let newItem = document .createElement ('li' );newItem.textContent = '替换后的内容' ; list.replaceChild (newItem, oldItem);
5. 克隆元素
1 2 3 let original = document .querySelector ('#card' );let clone = original.cloneNode (true ); let cloneShallow = original.cloneNode (false );
六、遍历 DOM 树
1. 父子关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 let element = document .querySelector ('#main' );let parent = element.parentNode ;let children = element.childNodes ;let childElements = element.children ;let firstChild = element.firstChild ;let firstElementChild = element.firstElementChild ;let lastChild = element.lastChild ;let lastElementChild = element.lastElementChild ;
2. 兄弟关系
1 2 3 4 5 6 7 8 9 10 11 12 13 let element = document .querySelector ('#target' );let prevSibling = element.previousSibling ;let prevElementSibling = element.previousElementSibling ;let nextSibling = element.nextSibling ;let nextElementSibling = element.nextElementSibling ;
七、事件处理
事件是 JavaScript 与用户交互的核心机制。
1. addEventListener 方法(推荐)
1 2 3 4 5 6 7 8 9 10 let button = document .querySelector ('#myButton' );button.addEventListener ('click' , function ( ) { alert ('按钮被点击了!' ); }); button.addEventListener ('mouseenter' , function ( ) { console .log ('鼠标进入了按钮区域' ); });
2. 常见事件类型
鼠标事件 :click、dblclick、mousedown、mouseup、mouseenter、mouseleave、mousemove
键盘事件 :keydown、keyup、keypress(已不推荐使用)
表单事件 :submit、change、input、focus、blur
窗口事件 :load、resize、scroll、beforeunload
3. 事件对象
事件处理函数会自动接收一个 event 参数,包含事件的详细信息。
1 2 3 4 5 6 7 document .querySelector ('#myInput' ).addEventListener ('keydown' , function (event ) { console .log ('按下的键:' + event.key ); console .log ('键码:' + event.keyCode ); event.preventDefault (); });
4. 事件冒泡与事件委托
事件冒泡是指当一个元素上的事件被触发时,这个事件会逐层向上传播到它的父元素。利用这个机制,可以实现事件委托 。
1 2 3 4 5 6 7 8 9 10 11 let list = document .querySelector ('#myList' );list.addEventListener ('click' , function (event ) { if (event.target .tagName === 'LI' ) { console .log ('点击了列表项:' + event.target .textContent ); } });
八、表单操作
1. 获取表单元素的值
1 2 3 4 5 let input = document .querySelector ('#username' );let value = input.value ; let checkbox = document .querySelector ('#agree' );let isChecked = checkbox.checked ;
2. 表单验证与提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let form = document .querySelector ('#loginForm' );form.addEventListener ('submit' , function (event ) { event.preventDefault (); let username = this .querySelector ('#username' ).value ; let password = this .querySelector ('#password' ).value ; if (username === '' || password === '' ) { alert ('请填写完整信息' ); return ; } console .log ('提交数据:' , { username, password }); });
九、元素位置与尺寸
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let element = document .querySelector ('#box' );let rect = element.getBoundingClientRect ();console .log (rect.top , rect.left , rect.width , rect.height );let scrollTop = element.scrollTop ;let scrollLeft = element.scrollLeft ;let clientWidth = element.clientWidth ;let clientHeight = element.clientHeight ;let offsetWidth = element.offsetWidth ;let offsetHeight = element.offsetHeight ;
总结
DOM 操作是 JavaScript 与网页交互的核心能力。掌握如何获取元素、修改内容与样式、动态调整结构、处理用户事件,是构建交互式网页应用的基础。通过 DOM API,你可以让网页从静态的 HTML 文档,转变为动态的、可交互的 Web 应用。熟练运用选择器、事件机制和 DOM 遍历方法,将使你能够高效地实现各种前端交互功能。