掌握DOM操作和事件处理是实现网页动态交互的基础技能。通过灵活地使用querySelector
、classList
和addEventListener
,可以轻松实现页面元素的动态修改和交互效果。同时,事件委托与冒泡机制是性能优化的重要手段,有助于更高效地管理事件。
DOM(Document Object Model,文档对象模型)是HTML和XML文档的编程接口。通过DOM,可以动态地访问和更改文档的内容、结构和样式。
1.1 获取DOM元素
1.1.1 getElementById
getElementById
是最常用的DOM选择方法,返回带有指定ID的元素对象。如果没有找到,则返回null
。
const title = document.getElementById('main-title');
console.log(title.textContent); // 输出元素内容
优点:
- 高效,速度快,直接返回匹配元素。
缺点: - 只能按
id
选择,局限性较大。
1.1.2 querySelector
和 querySelectorAll
querySelector
返回匹配指定CSS选择器的第一个元素。querySelectorAll
返回所有匹配选择器的节点集合(NodeList)。
const firstItem = document.querySelector('.list-item'); // 选择类名为list-item的第一个元素
const allItems = document.querySelectorAll('.list-item'); // 选择所有匹配项
console.log(firstItem);
console.log(allItems.length); // 返回所有匹配元素的数量
优点:
- 语法灵活,支持复杂的CSS选择器,如
.class
、#id
、div > p
等。
缺点: querySelectorAll
返回的NodeList是静态的,不会实时更新。
二、事件绑定与监听
事件处理是网页交互的核心。例如,点击按钮、输入文本、提交表单等,都可以通过事件监听器(Event Listener)来响应。
2.1 绑定事件
addEventListener
可以给元素添加事件监听器,即在触发事件时执行指定的回调函数。
const button = document.getElementById('submit-btn');
button.addEventListener('click', () => {
alert('按钮被点击了!');
});
语法:
element.addEventListener(event, callback, useCapture);
event
:事件类型,如click
、mouseover
、keydown
等。callback
:事件发生时执行的函数。useCapture
(可选):默认为false
,表示事件冒泡阶段触发,设为true
时表示在捕获阶段触发。
2.2 解绑事件
可以使用removeEventListener
移除事件监听器。
function showAlert() {
alert('绑定的事件');
}
button.addEventListener('click', showAlert);
button.removeEventListener('click', showAlert);
注意: 匿名函数无法被移除,必须使用命名函数。
三、事件委托与冒泡机制
3.1 事件冒泡(Event Bubbling)
事件冒泡指的是事件从目标元素开始,逐层向上冒泡到根节点(document
)。
<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
document.getElementById('list').addEventListener('click', function(event) {
console.log('UL被点击');
});
document.querySelector('li').addEventListener('click', function(event) {
console.log('LI被点击');
});
点击li
元素时:
LI被点击
UL被点击
这是事件冒泡的结果。
3.2 事件委托(Event Delegation)
事件委托是将事件监听器绑定在父元素上,通过event.target
属性判断触发事件的子元素。
document.getElementById('list').addEventListener('click', function(event) {
if (event.target.tagName === 'LI') {
console.log('点击了' + event.target.textContent);
}
});
优点:
- 避免给多个子元素分别绑定事件,减少性能消耗。
- 动态生成的子元素也能响应事件。
四、操作样式和类名
4.1 修改元素样式
可以直接修改元素的样式属性。
const box = document.getElementById('box');
box.style.backgroundColor = 'red';
box.style.fontSize = '20px';
注意: 直接修改style
只能设置行内样式,不推荐过度使用。
4.2 操作类名(classList)
使用classList
可以方便地添加、删除或切换类名。
const box = document.getElementById('box');
box.classList.add('active'); // 添加类名
box.classList.remove('hidden'); // 删除类名
box.classList.toggle('highlight'); // 切换类名(如果有就移除,没有就添加)
优点:
- 代码简洁,易读性强。
- 更符合CSS样式管理的方式,推荐使用。
五、创建与删除节点
DOM允许动态创建或删除HTML元素。
5.1 创建节点
createElement
创建新元素。appendChild
将元素添加到父节点中。
const newItem = document.createElement('li');
newItem.textContent = 'New Item';
document.getElementById('list').appendChild(newItem);
5.2 插入节点
insertBefore
可以在指定位置插入节点。
const list = document.getElementById('list');
const newItem = document.createElement('li');
newItem.textContent = 'Inserted Item';
list.insertBefore(newItem, list.children[1]); // 在第二个子元素前插入
5.3 删除节点
removeChild
删除子节点。
const list = document.getElementById('list');
const item = list.querySelector('li');
list.removeChild(item); // 删除第一个<li>元素
5.4 替换节点
replaceChild
替换子节点。
const list = document.getElementById('list');
const newItem = document.createElement('li');
newItem.textContent = 'Replaced Item';
list.replaceChild(newItem, list.children[0]); // 替换第一个子元素
六、案例:动态表单添加与删除项
<div>
<ul id="dynamic-list">
<li>Item 1</li>
<li>Item 2</li>
</ul>
<button id="add-item">添加项</button>
</div>
document.getElementById('add-item').addEventListener('click', function() {
const newItem = document.createElement('li');
newItem.textContent = `Item ${document.querySelectorAll('#dynamic-list li').length + 1}`;
document.getElementById('dynamic-list').appendChild(newItem);
});
每次点击按钮都会动态添加新的列表项。