【Web APIs-Day1】DOM操作基础

1 阅读4分钟

【Web APIs-Day1】DOM操作基础

📺 对应视频:P78-P93 | 🎯 核心目标:理解DOM树、掌握获取元素的多种方式、修改内容/属性/样式、使用定时器


一、Web APIs 概述

1.1 API 是什么?

API(Application Programming Interface)是接口,是别人封装好的功能,我们直接调用。

Web APIs 是浏览器提供的接口,分两大类:

  • DOM(Document Object Model):操作 HTML 文档
  • BOM(Browser Object Model):操作浏览器窗口

1.2 DOM 是什么?

DOM 将 HTML 文档映射为一个树形结构,每个 HTML 标签都是树上的一个节点(Node)

document(文档节点)
└── html(元素节点)
    ├── head
    │   └── title#text "标题")
    └── body
        ├── div#app
        │   ├── h1#text "Hello")
        │   └── p#text "World")
        └── script

节点类型:

  • 元素节点(Element) :HTML 标签,如 <div>
  • 文本节点(Text) :标签内的文本内容
  • 属性节点(Attr) :标签的属性,如 class="box"
  • 注释节点(Comment) :HTML 注释

二、获取 DOM 元素

2.1 新式 API(推荐)

// querySelector:获取匹配CSS选择器的第一个元素
document.querySelector('.box')         // 类名
document.querySelector('#title')       // id
document.querySelector('p')            // 标签
document.querySelector('.list li:first-child')  // 复杂选择器

// querySelectorAll:获取所有匹配的元素(NodeList)
document.querySelectorAll('li')         // 所有 li
document.querySelectorAll('.item')      // 所有 class=item 的元素

// ⚠️ querySelectorAll 返回 NodeList(类数组),需要遍历
const items = document.querySelectorAll('.item')
items.forEach(item => {
  console.log(item.textContent)
})

2.2 旧式 API(了解)

document.getElementById('myId')           // 通过 id 获取
document.getElementsByClassName('myClass') // 通过类名获取(HTMLCollection)
document.getElementsByTagName('div')       // 通过标签名获取

// 特殊元素
document.body       // body 元素
document.head       // head 元素
document.title      // title 文本
document.documentElement  // html 元素

💡 推荐:日常开发使用 querySelectorquerySelectorAll,语法与 CSS 选择器一致,学习成本低。


三、操作元素内容

3.1 textContent vs innerHTML

let div = document.querySelector('div')

// textContent:纯文本内容(安全,推荐用于纯文本)
div.textContent            // 获取(包含所有后代文本)
div.textContent = '<b>粗体</b>'  // 设置(标签会被当作文本显示,不解析)

// innerHTML:HTML 内容(可以解析标签)
div.innerHTML              // 获取(包含HTML标签)
div.innerHTML = '<b>粗体</b>'  // 设置(会解析并渲染 HTML)

// ⚠️ 安全警告:innerHTML 存在 XSS 风险,绝对不要将用户输入直接放入 innerHTML
// 错误示范:
div.innerHTML = userInput  // 如果 userInput = '<script>恶意代码</script>'

四、操作元素属性

4.1 HTML 标准属性

let img = document.querySelector('img')
let input = document.querySelector('input')
let a = document.querySelector('a')

// 读写标准属性(直接通过属性名)
img.src = 'https://example.com/pic.jpg'
img.alt = '图片描述'
a.href = 'https://juejin.cn'
input.value = '输入框的值'
input.type = 'password'
input.checked = true     // 复选框选中
input.disabled = false   // 是否禁用

4.2 自定义属性(data-* 属性)

<!-- HTML -->
<div id="box" data-id="123" data-user-name="张三"></div>
let box = document.querySelector('#box')

// 读取 data-* 属性
box.dataset.id        // '123'
box.dataset.userName  // '张三'(驼峰命名,去掉 data-,连字符转驼峰)

// 设置 data-* 属性
box.dataset.status = 'active'  // 自动添加 data-status 属性

4.3 getAttribute / setAttribute / removeAttribute

// 处理非标准属性 or 需要精确控制时使用
let el = document.querySelector('.box')

el.getAttribute('class')         // 'box'
el.getAttribute('data-id')       // '123'(也可以读 data-*)
el.setAttribute('data-id', '456')
el.removeAttribute('data-id')
el.hasAttribute('data-id')       // false(删除后)

五、操作样式

5.1 行内样式(style 属性)

let box = document.querySelector('.box')

// 设置单个样式(CSS属性名转驼峰命名)
box.style.width = '200px'
box.style.backgroundColor = 'red'   // background-color → backgroundColor
box.style.fontSize = '18px'
box.style.display = 'none'          // 隐藏元素

// 读取行内样式
console.log(box.style.width)         // '200px'(只能读行内样式)
console.log(box.style.color)         // ''(如果样式在CSS文件里,读不到)

5.2 className 操作

// className(字符串操作,替换所有类名)
box.className = 'active'         // 替换(覆盖原来的类名,危险!)
box.className += ' active'       // 追加(容易加空格bug)

5.3 classList 操作(推荐)

let box = document.querySelector('.box')

// classList 方法(精准操作类名)
box.classList.add('active')        // 添加类名
box.classList.remove('active')     // 移除类名
box.classList.toggle('active')     // 有就删,没有就加(切换状态)
box.classList.contains('active')   // 是否包含某类名(返回布尔)
box.classList.replace('old', 'new') // 替换类名

// 实际应用:点击切换 active 状态
btn.addEventListener('click', () => {
  box.classList.toggle('active')
})

5.4 getComputedStyle(读取计算后样式)

// 读取实际生效的样式(包括CSS文件中的)
let style = getComputedStyle(box)
console.log(style.width)           // '200px'(计算后的值)
console.log(style.backgroundColor) // 'rgb(255, 0, 0)'

六、定时器

6.1 setTimeout(延迟执行)

// 语法:setTimeout(回调函数, 延迟毫秒数)
let timer = setTimeout(() => {
  console.log('2秒后执行')
}, 2000)

// 取消定时器
clearTimeout(timer)

// 实际应用:自动关闭弹窗
function showAlert(msg, delay = 3000) {
  const box = document.createElement('div')
  box.textContent = msg
  document.body.appendChild(box)
  setTimeout(() => box.remove(), delay)
}

6.2 setInterval(重复执行)

// 语法:setInterval(回调函数, 间隔毫秒数)
let count = 0
let interval = setInterval(() => {
  count++
  console.log(`第${count}次`)
  if (count >= 5) clearInterval(interval)  // 执行5次后停止
}, 1000)

// 取消定时器
clearInterval(interval)

实际应用:倒计时

function countdown(seconds) {
  let remaining = seconds
  const display = document.querySelector('#countdown')
  
  display.textContent = remaining
  
  const timer = setInterval(() => {
    remaining--
    display.textContent = remaining
    if (remaining <= 0) {
      clearInterval(timer)
      display.textContent = '时间到!'
    }
  }, 1000)
}
countdown(60)  // 60秒倒计时

七、综合案例

案例1:轮播图自动播放

const images = ['img1.jpg', 'img2.jpg', 'img3.jpg']
const img = document.querySelector('.banner img')
let current = 0

setInterval(() => {
  current = (current + 1) % images.length
  img.src = images[current]
}, 3000)

案例2:随机更换背景色

function randomColor() {
  const r = Math.floor(Math.random() * 256)
  const g = Math.floor(Math.random() * 256)
  const b = Math.floor(Math.random() * 256)
  return `rgb(${r}, ${g}, ${b})`
}

setInterval(() => {
  document.body.style.backgroundColor = randomColor()
}, 1000)

八、知识图谱

DOM 操作基础
├── DOM 树
│   └── 节点类型:元素、文本、属性、注释
├── 获取元素
│   ├── querySelector(单个)
│   ├── querySelectorAll(多个,NodeList)
│   └── 旧式:getElementById/ByClassName/ByTagName
├── 操作内容
│   ├── textContent(纯文本,安全)
│   └── innerHTML(HTML,注意XSS)
├── 操作属性
│   ├── 标准属性:el.src / el.href 等
│   ├── data-* 属性:el.dataset.xxx
│   └── getAttribute/setAttribute/removeAttribute
├── 操作样式
│   ├── el.style.xxx(行内,驼峰命名)
│   ├── el.classList(add/remove/toggle/contains)
│   └── getComputedStyle(读取计算样式)
└── 定时器
    ├── setTimeout(延迟,clearTimeout取消)
    └── setInterval(重复,clearInterval取消)

九、高频面试题

Q1: textContent innerHTML 的区别?

textContent 只处理纯文本,不解析 HTML 标签,更安全;innerHTML 会解析和渲染 HTML。当内容来自用户输入时必须用 textContent,避免 XSS 攻击。

Q2: querySelector getElementById 有什么区别?

querySelector 接受完整的 CSS 选择器,更灵活;getElementById 只能通过 id 查找,但性能略好(直接查 id 索引)。现代开发推荐 querySelector

Q3:如何读取 CSS 文件中定义的样式?

element.style.xxx 只能读行内样式;要读 CSS 文件中的样式,用 getComputedStyle(element).xxx,它返回元素实际计算后的最终样式值。


⬅️ 上一篇JS基础Day5 - 对象与内置对象 ➡️ 下一篇Web APIs Day2 - 事件监听与事件对象