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 遍历方法,将使你能够高效地实现各种前端交互功能。