DOM入門,理解文檔對象模型
一、什么是DOM?
DOM全稱是Document Object Model(文檔對象模型), 它是HTML和XML文檔的編程接口. 簡單來說, DOM就是把我們的網頁文檔轉換成了一個對象模型, 這樣我們就可以用JavaScript來操作網頁了.
想象一下: 你寫了一個HTML文件, 瀏覽器加載這個文件后, 會把它解析成一個樹狀結構, 這個結構就是DOM. 通過DOM, 我們可以:
- 改變網頁的內容.
- 修改元素的樣式.
- 添加或刪除元素.
- 響應用戶的交互.
示例代碼:
//舉個最簡單的例子
document.getElementById('myButton').addEventListener('click', function() {
alert('按鈕被點擊了!');
});二、DOM樹結構解析
DOM的核心概念是"樹結構", 讓我們用一個簡單的HTML例子來說明:
<!DOCTYPE html>
<html>
<head>
<title>我的網頁</title>
</head>
<body>
<h1>歡迎來到我的網站</h1>
<div class="content">
<p>這是一個段落</p>
<p>這是另一個段落</p>
</div>
</body>
</html>這個HTML會被瀏覽器解析成如下的DOM樹:
文檔 (Document)
└── html (根元素)
├── head
│ └── title
│ └── "我的網頁" (文本節點)
└── body
├── h1
│ └── "歡迎來到我的網站" (文本節點)
└── div (class="content")
├── p
│ └── "這是一個段落" (文本節點)
└── p
└── "這是另一個段落" (文本節點)這個樹狀結構有幾個關鍵點:
- 文檔節點(Document): 這是整個DOM樹的根節點,代表整個文檔.
- 元素節點(Element): 如<html>, <head>, <body>, <div>等.
- 文本節點(Text): 如標簽內的文字內容.
- 屬性節點(Attribute): 如class="content".
三、節點類型詳解
1) 元素節點
這是最常見的節點類型, 對應HTML標簽. 比如<div>, <p>, <a>等.
const divElement = document.createElement('div');
console.log(divElement.nodeType); // 1
console.log(divElement.nodeType === Node.ELEMENT_NODE); // true2) 文本節點
包含元素的文本內容.
const textNode = document.createTextNode('你好,世界!');
console.log(textNode.nodeType); // 33) 注釋節點
對應HTML中的注釋.
const comment = document.createComment('這是一個注釋');
console.log(comment.nodeType); // 84)文檔節點
代表整個文檔, 即document對象.
console.log(document.nodeType); // 95) 節點之間的關系
DOM節點之間有多種關系:
- parentNode: 父節點.
- childNodes: 所有子節點的列表(包括文本節點等).
- children: 僅元素子節點.
- firstChild/lastChild: 第一個/最后一個子節點.
- nextSibling/previousSibling: 下一個/上一個兄弟節點.
我們來看個示例:
<div id="container">
<p>段落1</p>
<p>段落2</p>
</div>const container = document.getElementById('container');
console.log(container.childNodes.length); //可能為5(包括文本節點和元素節點)
console.log(container.children.length); //2(只有p元素)四、DOM操作基礎
1) 查詢元素
// 通過ID獲取
const element = document.getElementById('myId');
// 通過類名獲取(返回HTMLCollection)
const elements = document.getElementsByClassName('myClass');
// 通過標簽名獲取(返回HTMLCollection)
const divs = document.getElementsByTagName('div');
// 通過CSS選擇器獲取(返回第一個匹配元素)
const item = document.querySelector('.menu-item');
// 通過CSS選擇器獲取所有匹配元素(返回NodeList)
const items = document.querySelectorAll('.menu-item');2)創建與添加元素
// 創建新元素
const newDiv = document.createElement('div');
newDiv.textContent = '我是新創建的div';
// 添加到文檔中
document.body.appendChild(newDiv);
// 插入到特定位置
const container = document.getElementById('container');
const firstChild = container.firstChild;
container.insertBefore(newDiv, firstChild);3) 修改元素
// 修改內容
element.textContent = '新文本內容';
element.innerHTML = '<strong>加粗文本</strong>';
// 修改樣式
element.style.color = 'red';
element.style.backgroundColor = '#f0f0f0';
// 修改類
element.classList.add('new-class');
element.classList.remove('old-class');
element.classList.toggle('active');4)刪除元素
// 移除子元素
const parent = document.getElementById('parent');
const child = document.getElementById('child');
parent.removeChild(child);
// 現代寫法(不需要知道父元素)
child.remove();五、DOM事件處理
基本事件處理:
const button = document.getElementById('myButton');
// 傳統方式
button.onclick = function() {
console.log('按鈕被點擊了!');
};
// 推薦方式(可以添加多個事件監聽器)
button.addEventListener('click', function(event) {
console.log('按鈕被點擊了!', event);
});事件冒泡和捕獲, DOM事件有三個階段:
- 捕獲階段(從window向下到目標元素).
- 目標階段(到達目標元素).
- 冒泡階段(從目標元素向上冒泡).
document.getElementById('outer').addEventListener('click', function() {
console.log('外層div - 冒泡階段');
}, false); // false或不傳表示冒泡階段
document.getElementById('inner').addEventListener('click', function() {
console.log('內層div - 捕獲階段');
}, true); // true表示捕獲階段利用事件冒泡機制,可以在父元素上處理子元素的事件.
<ul id="myList">
<li>項目1</li>
<li>項目2</li>
<li>項目3</li>
</ul>document.getElementById('myList').addEventListener('click', function(event) {
if (event.target.tagName === 'LI') {
console.log('點擊了:', event.target.textContent);
}
});六、DOM標準與綜合示例
DOM級別:
- DOM Level 1 (1998): 定義了核心DOM和HTML DOM.
- DOM Level 2 (2000): 添加了事件模型、樣式訪問等.
- DOM Level 3 (2004): 擴展了DOM核心,添加了XPath等.
- DOM Level 4 (2015): 也稱為DOM Living Standard,現代瀏覽器主要實現.
兼容性問題, 雖然現代瀏覽器對DOM的支持已經很好,但仍有一些需要注意的差異:
- IE的差異:IE8及以下不支持addEventListener, 需要使用attachEvent.IE對某些CSS屬性的訪問方式不同.
- 方法可用性:remove()方法在舊瀏覽器中不可用.classList在IE9及以下不支持.
- 事件對象:在IE中, 事件對象是全局的window.event.在其他瀏覽器中, 事件對象作為參數傳遞.
兼容性的操作示例:
//兼容性事件處理示例
function addEvent(element, eventName, handler) {
if (element.addEventListener) {
element.addEventListener(eventName, handler);
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, handler);
} else {
element['on' + eventName] = handler;
}
}
//兼容性事件對象獲取
element.onclick = function(event) {
event = event || window.event;
const target = event.target || event.srcElement;
// 處理事件...
};綜合示例, 構建一個簡單的待辦事項列表:
<!DOCTYPE html>
<html>
<head>
<title>待辦事項</title>
<style>
.completed {
text-decoration: line-through;
color: #999;
}
</style>
</head>
<body>
<h1>我的待辦事項</h1>
<input type="text" id="newTodo" placeholder="輸入新任務">
<button id="addBtn">添加</button>
<ul id="todoList"></ul>
<script>
document.addEventListener('DOMContentLoaded', function() {
const newTodoInput = document.getElementById('newTodo');
const addBtn = document.getElementById('addBtn');
const todoList = document.getElementById('todoList');
// 添加新任務
function addTodo() {
const text = newTodoInput.value.trim();
if (text) {
const li = document.createElement('li');
const span = document.createElement('span');
span.textContent = text;
const deleteBtn = document.createElement('button');
deleteBtn.textContent = '刪除';
li.appendChild(span);
li.appendChild(deleteBtn);
todoList.appendChild(li);
newTodoInput.value = '';
// 添加點擊事件(完成任務)
span.addEventListener('click', function() {
span.classList.toggle('completed');
});
// 添加刪除按鈕事件
deleteBtn.addEventListener('click', function() {
li.remove();
});
}
}
// 點擊按鈕添加
addBtn.addEventListener('click', addTodo);
// 按回車鍵添加
newTodoInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
addTodo();
}
});
});
</script>
</body>
</html>這個例子展示了:
- 動態創建DOM元素
- 事件監聽
- 類名切換
- 元素刪除
- 表單處理



















