主题
DOM 操作
这一页只聚焦最常见的 DOM 查询、遍历和增删改操作。尺寸、坐标、事件和 Observer 已经拆成独立专题,不再混在同一页里。
查询入口
文档对象
js
document
window.document
node.ownerDocument查询单个或多个元素
js
document.querySelector('.card')
document.querySelectorAll('.card')如果要在某个元素范围内继续查找,也可以从元素自身开始:
js
const section = document.querySelector('.section')
section.querySelector('.title')
section.querySelectorAll('button')提示
querySelectorAll()返回静态集合。getElementsByClassName()、getElementsByTagName()返回动态集合。
常见文档级入口
js
document.documentElement
document.head
document.body遍历关系
父子关系
js
el.parentNode
el.parentElement
el.childNodes
el.children
el.firstChild
el.firstElementChild
el.lastChild
el.lastElementChildchildNodes 会包含文本节点和注释节点,children 只包含元素节点。
兄弟关系
js
el.previousSibling
el.previousElementSibling
el.nextSibling
el.nextElementSibling匹配和向上查找
js
el.matches('.is-active')
el.closest('.card')matches() 用于判断当前元素是否符合某个选择器,closest() 用于从当前元素开始向上查找最近的匹配祖先元素。
属性与数据
读取和设置属性
js
el.getAttribute('id')
el.setAttribute('aria-hidden', 'true')
el.removeAttribute('hidden')
el.hasAttribute('disabled')data-* 和 dataset
js
el.setAttribute('data-theme', 'dark')
el.dataset.theme = 'dark'
console.log(el.dataset.theme)当属性语义明确且与 DOM 结构相关时,用原生属性;当只是给脚本附带少量页面数据时,用 data-* 更合适。
类名与样式
类名操作
js
el.className
el.classList.add('active')
el.classList.remove('hidden')
el.classList.toggle('open')
el.classList.replace('show', 'hide')
el.classList.contains('active')className 是整段字符串,classList 是更适合增删改查的接口。
内联样式与计算样式
js
el.style.color = '#1677ff'
el.style.display = 'none'
window.getComputedStyle(el).display
window.getComputedStyle(el, '::before').contentel.style 只能读写内联样式;如果要获取元素最终生效的样式,应使用 getComputedStyle()。
创建与插入
创建节点
js
const div = document.createElement('div')
div.textContent = 'hello'插入到容器中
js
container.append(div)
container.prepend(div)如果要把新节点插到某个已有节点的前后,可以使用:
js
el.before(newNode)
el.after(newNode)使用 insertAdjacentHTML
当手里是 HTML 字符串时,可以使用:
js
el.insertAdjacentHTML('beforebegin', '<p>before</p>')
el.insertAdjacentHTML('afterbegin', '<p>first child</p>')
el.insertAdjacentHTML('beforeend', '<p>last child</p>')
el.insertAdjacentHTML('afterend', '<p>after</p>')四个位置分别表示:
beforebegin:元素外部前面afterbegin:元素内部最前面beforeend:元素内部最后面afterend:元素外部后面
如果插入的是不可信字符串,需要注意 XSS 风险。
批量插入
js
const fragment = document.createDocumentFragment()
items.forEach((item) => {
const li = document.createElement('li')
li.textContent = item
fragment.append(li)
})
list.append(fragment)DocumentFragment 适合先在内存里组装,再统一挂入页面。
替换、删除与复制
替换节点
js
oldNode.replaceWith(newNode)
parentNode.replaceChild(newNode, oldNode)删除节点
js
el.remove()
parentNode.removeChild(el)清空内容
js
el.textContent = ''
el.innerHTML = ''如果只想移除文本内容,优先用 textContent;如果需要清掉整个 HTML 结构,才使用 innerHTML。
复制和包含判断
js
const copy = el.cloneNode(true)
el.contains(node)cloneNode(true) 会深拷贝子节点,contains() 用于判断某个节点是否位于当前节点内部。
文本与 HTML
读取文本
js
el.textContent
el.innerText两者区别是:
textContent不关心 CSS,可拿到原始文本节点内容。innerText会受样式和布局影响,更接近“页面上看到的文本”。
设置文本
js
el.textContent = 'hello'
el.innerText = 'hello'当内容本质是纯文本时,优先使用 textContent。
读取和写入 HTML
js
el.innerHTML
el.innerHTML = '<strong>hello</strong>'innerHTML 适合在明确需要解析 HTML 字符串时使用,但也最容易引入注入风险。
其他常见对象
iframe
js
iframe.contentWindow
iframe.contentDocument只有在同源前提下,contentDocument 才能被正常访问,否则通常会得到 null 或触发跨源限制。
DOMParser
js
const parser = new DOMParser()
const doc = parser.parseFromString('<p>Hello</p>', 'text/html')DOMParser 用于把字符串解析成可操作的文档对象,适合做离线解析、提取和转换。
