跳转至

🌐 DOM / BOM 操作与 Web API 实战

JS 基础 / JS 高级进阶 偏"语言核心",本篇补齐 JS 与页面、与后端对话的桥梁:DOM 操作、事件、浏览器存储、网络请求(Fetch)、常用 Web API。依据 WHATWG DOM 标准W3CMDN

适用:所有开发者——前端写交互、后端理解"前端到底怎么调我接口"。


一、DOM:文档对象模型

浏览器把 HTML 解析成树,JS 通过 document 操作这棵树。

// 查
const el = document.querySelector('#app');
const items = document.querySelectorAll('.item');   // NodeList
// 增
const div = document.createElement('div');
div.textContent = '新节点';
el.appendChild(div);
// 改
el.classList.add('active');
el.style.color = 'red';
el.setAttribute('data-id', '1');
// 删
el.remove();

死角 1:querySelectorAll 不是数组

它是 NodeList,没有 map/filter。转数组:[...items].map(...)Array.from(items)

性能:缓存 DOM 引用

频繁操作同一元素时把 const el = document.querySelector(...) 提出来,避免每次查 DOM(重排代价高)。


二、事件:用户交互的入口

btn.addEventListener('click', (e) => {
  e.preventDefault();          // 阻止默认行为(如表单提交跳转)
  console.log(e.target);       // 实际触发元素
});

// 事件委托(重点!)
list.addEventListener('click', (e) => {
  if (e.target.matches('li')) {
    console.log('点了', e.target.textContent);  // 动态新增的 li 也能响应
  }
});

死角 2:事件委托必须在父级监听

给每个 li 单独 addEventListenerli 动态增删时会失效;用事件委托(监听不变的共同父级)天然支持动态内容,且省内存。

卸载别忘了

SPA 组件销毁时移除监听(removeEventListener),否则内存泄漏(见 JS 高级进阶 内存章节)。


三、浏览器存储(前端"数据库")

API 容量 生命周期 场景
localStorage ~5MB 永久(手动清) 记住登录 token、主题
sessionStorage ~5MB 标签页关闭即清 临时表单草稿
cookie ~4KB 可设过期 后端会话(自动随请求发送)
IndexedDB 数百 MB 永久 离线应用、大量结构化数据
localStorage.setItem('token', 'abc');
const t = localStorage.getItem('token');
localStorage.removeItem('token');

// cookie 由后端 Set-Cookie 下发,JS 可读 document.cookie(受 HttpOnly 限制)

死角 3:localStorage 只能存字符串

setItem('k', {a:1}) 存进去的是 "[object Object]"。对象要先 JSON.stringify,取回 JSON.parse

死角 4:别在 localStorage 存敏感信息

token 可被 XSS 窃取。敏感鉴权用 HttpOnly + Secure cookie(见 前端安全全集)。


四、Fetch:前端调后端的姿势

// GET
const res = await fetch('/api/users');
const data = await res.json();

// POST
const r = await fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: '鱼樱' }),
});
if (!r.ok) throw new Error('HTTP ' + r.status);
const created = await r.json();

死角 5:fetch 不抛网络错误以外的异常

HTTP 404/500 不会 reject,只有断网才 reject。必须 if (!res.ok) 手动判断。

封装建议

项目里别裸写 fetch,封装一层统一加 baseURL、token、错误处理,放在 src/api/ 目录(后端联调看 给后端的前端速通)。


五、高频 Web API 速查

API 用途 示例
IntersectionObserver 元素进入视口(懒加载/无限滚动) new IntersectionObserver(cb).observe(el)
URLSearchParams 解析/构造查询串 new URLSearchParams(location搜)
Clipboard 复制粘贴 navigator.clipboard.writeText('x')
WebSocket 全双工实时通信 new WebSocket('ws://...')
ResizeObserver 监听尺寸变化 响应式组件内部用
matchMedia JS 里读媒体查询 window.matchMedia('(max-width:768px)')
requestAnimationFrame 动画下一帧(比 setInterval 流畅) 见性能章

市场价值

IntersectionObserver 做图片懒加载和无限滚动是性能优化标配;WebSocket 是实时聊天/看板的基础。后端如果能懂这些,接口设计会更对路。


六、Web API 自检清单

  • 会用 querySelector/querySelectorAll 操作 DOM
  • 理解事件委托并在动态列表使用
  • 区分 localStorage/sessionStorage/cookie 用途
  • 会写带错误判断的 fetch
  • 知道 IntersectionObserver / WebSocket 解决什么问题

进阶:异步机制见 JS 高级进阶;性能见 浏览器渲染与性能总纲