什么是 DOM?常见 DOM 操作有哪些?
DOM(Document Object Model)
DOM 是 HTML/XML 文档的编程接口,将文档表示为树形结构,JavaScript 可以通过 DOM API 操作页面内容。
document
└── html
├── head
│ ├── title
│ └── meta
└── body
├── div
│ └── p
└── script获取元素
// 现代 API
document.querySelector('#id') // CSS 选择器,返回第一个
document.querySelectorAll('.class') // 返回 NodeList
// 传统 API
document.getElementById('id')
document.getElementsByClassName('class') // HTMLCollection(动态)
document.getElementsByTagName('div') // HTMLCollection(动态)创建和添加
// 创建
const div = document.createElement('div')
div.textContent = 'Hello'
div.className = 'box'
div.setAttribute('data-id', '1')
// 添加
document.body.appendChild(div) // 追加到末尾
document.body.insertBefore(div, refEl) // 在指定元素前插入
document.body.append(div, 'text') // 支持多参数和文本
// 现代 API
parentEl.prepend(newEl) // 开头插入
parentEl.before(newEl) // 元素前插入
parentEl.after(newEl) // 元素后插入删除和替换
// 删除
el.remove() // 现代 API
parentEl.removeChild(el) // 传统 API
// 替换
parentEl.replaceChild(newEl, oldEl)
oldEl.replaceWith(newEl) // 现代 API修改内容和属性
// 内容
el.textContent = '纯文本' // 安全(自动转义)
el.innerHTML = '<b>HTML</b>' // 可解析 HTML(注意 XSS)
el.innerText = '可见文本' // 触发重排
// 属性
el.id = 'myId'
el.className = 'box active'
el.classList.add('active') // 添加 class
el.classList.remove('active') // 移除 class
el.classList.toggle('active') // 切换 class
el.classList.contains('active') // 是否包含
// dataset
el.dataset.userId = '123' // data-user-id="123"
// 样式
el.style.color = 'red'
el.style.setProperty('--custom', 'value')遍历
el.parentNode // 父节点
el.parentElement // 父元素节点
el.children // 子元素集合
el.firstChild // 第一个子节点(可能是文本节点)
el.firstElementChild // 第一个元素子节点
el.nextElementSibling // 下一个兄弟元素性能优化
1. 使用 DocumentFragment 批量操作
const fragment = document.createDocumentFragment()
items.forEach(item => {
const li = document.createElement('li')
li.textContent = item
fragment.appendChild(li)
})
ul.appendChild(fragment) // 只触发一次重排2. cloneNode 替代 createElement
const template = document.createElement('div')
template.className = 'item'
template.innerHTML = '<span></span>'
const clone = template.cloneNode(true) // 深拷贝
clone.querySelector('span').textContent = 'Hello'3. innerHTML vs createElementinnerHTML 解析 HTML 字符串,大量元素时比 createElement 快,但有 XSS 风险。
MutationObserver(监听 DOM 变化)
const observer = new MutationObserver((mutations) => {
mutations.forEach(m => console.log(m.type))
})
observer.observe(el, { childList: true, subtree: true, attributes: true })