FORMA

浏览器相关 API

DOM 事件、存储、fetch、Worker、Observer 等由浏览器提供的 Web API(非 ECMAScript 核心)。HTML 结构见 标签

一、DOM 与事件

1. 事件流(捕获 → 目标 → 冒泡)

事件传播分为三个阶段:

  • 捕获阶段(capture phase):从 window 向下传播到目标元素。
  • 目标阶段(target phase):到达目标元素。
  • 冒泡阶段(bubble phase):从目标元素向上传播回 window

默认情况下,事件在冒泡阶段触发。通过 addEventListener 的第三个参数可调整。

2. addEventListeneruseCaptureonce

js
element.addEventListener("click", handler, {
    capture: true, // 在捕获阶段触发(默认为 false 冒泡阶段)
    once: true, // 触发一次后自动移除监听
});

// 旧版写法:第三个参数为布尔值表示 useCapture
element.addEventListener("click", handler, true);

常用模式

  • 阻止冒泡:event.stopPropagation()
  • 阻止默认行为:event.preventDefault()

3. 事件委托原理与性能优化

原理:利用事件冒泡,在父元素上监听事件,通过 event.target 判断实际触发的子元素。

优点

  • 减少内存占用(无需为每个子元素绑定监听)。
  • 动态添加的子元素自动拥有事件响应。

示例

js
document.getElementById("list").addEventListener("click", e => {
    if (e.target.matches("li.item")) {
        console.log("点击了", e.target.textContent);
    }
});

4. 自定义事件(CustomEvent

用于组件通信或解耦逻辑。

js
// 创建并派发
const event = new CustomEvent("myEvent", { detail: { id: 123 } });
element.dispatchEvent(event);

// 监听
element.addEventListener("myEvent", e => {
    console.log(e.detail.id);
});

5. MutationObserver – 监听 DOM 变化

异步监听 DOM 树的变化(属性、子节点、文本等)。

js
const observer = new MutationObserver(mutationsList => {
    for (const mutation of mutationsList) {
        if (mutation.type === "childList") {
            console.log("子节点变化");
        }
    }
});
observer.observe(targetNode, {
    attributes: true,
    childList: true,
    subtree: true,
});
// 停止监听
observer.disconnect();

6. IntersectionObserver – 懒加载、无限滚动

异步观察目标元素与视口(或指定祖先元素)的交叉状态。

js
const observer = new IntersectionObserver(
    entries => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                // 进入视口,加载图片或更多数据
                loadImage(entry.target);
                observer.unobserve(entry.target); // 一次加载后停止观察
            }
        });
    },
    { threshold: 0.1 }
);
observer.observe(imgElement);

应用:图片懒加载、无限滚动列表、曝光统计。

7. ResizeObserver – 监听元素尺寸变化

window.resize 更精确,可观察任意元素。

js
const resizeObserver = new ResizeObserver(entries => {
    for (let entry of entries) {
        console.log(entry.contentRect.width, entry.contentRect.height);
    }
});
resizeObserver.observe(someElement);

二、BOM 操作(浏览器对象模型)

1. history 对象 – SPA 路由核心

  • history.pushState(state, title, url):添加历史记录,不刷新页面。
  • history.replaceState(state, title, url):替换当前历史记录。
  • window.onpopstate:监听浏览器前进/后退。
js
// 简易 SPA 路由
window.addEventListener("popstate", () => {
    const path = location.pathname;
    renderView(path);
});

2. navigator – 浏览器与设备信息

常用属性:

  • navigator.userAgent:用户代理字符串。
  • navigator.language:当前语言。
  • navigator.onLine:是否在线。
  • navigator.geolocation:地理位置。
  • navigator.clipboard:剪贴板 API(见下文)。
  • navigator.serviceWorker:Service Worker 注册。

3. screen – 屏幕信息

  • screen.width/height:屏幕分辨率。
  • screen.availWidth/availHeight:可用区域(排除任务栏)。
  • screen.colorDepth:色彩深度。

4. location – URL 精细操作

js
// 获取参数
const urlParams = new URLSearchParams(location.search);
const id = urlParams.get("id");

// 跳转
location.href = "https://example.com";
location.assign("https://example.com");
location.replace("https://example.com"); // 无历史记录
location.reload();

// 获取各部分
location.protocol; // "https:"
location.host; // "example.com:8080"
location.pathname; // "/path"
location.hash; // "#section"

三、Canvas 与 WebGL 基础(简要)

1. Canvas 2D

js
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 100, 50);
ctx.beginPath();
ctx.arc(200, 75, 40, 0, 2 * Math.PI);
ctx.stroke();

常用:像素处理 getImageData/putImageData、绘制图像 drawImage、动画 requestAnimationFrame

2. WebGL(基于 OpenGL ES)

用于高性能 3D/2D 图形渲染(如 Three.js 底层)。

js
const gl = canvas.getContext("webgl");
// 编写着色器、缓冲区等,通常借助 Three.js 等库简化开发。

四、Web 存储

1. localStorage / sessionStorage

  • 容量:约 5-10MB。
  • 同步 APIsetItemgetItemremoveItemclear
  • 存储类型:字符串(其他类型需 JSON.stringify/parse)。
  • 生命周期localStorage 永久;sessionStorage 为标签页关闭即清除。

监听 storage 事件(仅在同源不同标签页间触发):

js
window.addEventListener("storage", e => {
    console.log(e.key, e.oldValue, e.newValue, e.url);
});

2. IndexedDB – 大型结构化数据存储

异步、事务、索引、支持大量数据。

js
const request = indexedDB.open("myDB", 1);
request.onsuccess = e => {
    const db = e.target.result;
    const transaction = db.transaction(["users"], "readwrite");
    const store = transaction.objectStore("users");
    store.add({ id: 1, name: "Alice" });
};

关键概念

  • 对象存储(类似表)
  • 索引(加速查询)
  • 游标(遍历数据)

3. Cookies 进阶属性

  • SameSiteStrict(完全禁止第三方请求携带)、Lax(部分允许)、None(需配合 Secure)。
  • Secure:仅 HTTPS 传输。
  • HttpOnly:禁止 JavaScript 访问,防止 XSS 窃取。
  • Max-Age / Expires:过期时间。
js
document.cookie = "token=abc; Secure; SameSite=Strict; Max-Age=3600";

五、网络请求

1. Fetch 完全指南

js
// 基本 GET
fetch("/api/data")
    .then(res => {
        if (!res.ok) throw new Error("HTTP error");
        return res.json();
    })
    .catch(err => console.error(err));

// POST with JSON
fetch("/api/post", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ foo: "bar" }),
});

// 请求/响应拦截(可通过封装或 Proxy 实现)
const originalFetch = window.fetch;
window.fetch = function (...args) {
    console.log("Request:", args);
    return originalFetch(...args).then(res => {
        console.log("Response:", res);
        return res;
    });
};

// 自定义 AbortSignal(中止请求)
const controller = new AbortController();
fetch("/api/long", { signal: controller.signal });
setTimeout(() => controller.abort(), 1000);

// Stream API 处理大文件(例如逐块读取)
const response = await fetch("/large-file");
const reader = response.body.getReader();
while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    console.log("Received chunk:", value);
}

2. XMLHttpRequest 进阶(进度监控)

js
const xhr = new XMLHttpRequest();
xhr.open("POST", "/upload");
xhr.upload.onprogress = e => {
    console.log(`Uploaded ${e.loaded}/${e.total}`);
};
xhr.onload = () => console.log("Done");
xhr.send(formData);

3. WebSocket – 全双工实时通信

js
const ws = new WebSocket("wss://example.com/socket");
ws.onopen = () => ws.send("Hello");
ws.onmessage = e => console.log("Received:", e.data);
ws.onerror = err => console.error(err);
ws.onclose = () => console.log("Closed");

// 重连机制示例
function connect() {
    const ws = new WebSocket(url);
    ws.onclose = () => setTimeout(connect, 1000);
}

4. Server-Sent Events (SSE) – 服务器单向推送

js
const evtSource = new EventSource("/events");
evtSource.onmessage = e => console.log("Data:", e.data);
evtSource.addEventListener("customEvent", e => {});

六、多线程

1. Web Worker(专用线程)

运行独立于主线程的脚本,用于密集计算。

js
// worker.js
self.onmessage = e => {
    const result = heavyCalculation(e.data);
    self.postMessage(result);
};

// main.js
const worker = new Worker("worker.js");
worker.postMessage(input);
worker.onmessage = e => console.log(e.data);

Shared Worker:多标签页共享一个 worker。 Service Worker:代理网络请求,实现离线缓存(PWA)、消息推送。

2. Service Worker(离线缓存 + 消息推送)

js
// 注册
navigator.serviceWorker.register("/sw.js");
// sw.js 中拦截 fetch 事件,返回缓存或网络响应
self.addEventListener("fetch", event => {
    event.respondWith(
        caches.match(event.request).then(resp => resp || fetch(event.request))
    );
});

3. SharedArrayBuffer 与原子操作(Atomics

用于多个 Worker 或主线程之间共享内存(需跨域隔离上下文)。

js
// 主线程
const sab = new SharedArrayBuffer(1024);
const int32 = new Int32Array(sab);
worker.postMessage(sab);

// Worker 中
Atomics.add(int32, 0, 1);
Atomics.notify(int32, 0, 1);

七、剪贴板 API

异步读写剪贴板(需用户授权):

js
// 写入文本
await navigator.clipboard.writeText("Hello World");
// 读取文本
const text = await navigator.clipboard.readText();
// 写入图片(ClipboardItem)
const imgBlob = await fetch("image.png").then(r => r.blob());
await navigator.clipboard.write([
    new ClipboardItem({ [imgBlob.type]: imgBlob }),
]);

八、全屏 API 与页面可见性

1. 全屏 API

js
// 进入全屏
document.documentElement.requestFullscreen();
// 退出全屏
document.exitFullscreen();
// 监听变化
document.addEventListener("fullscreenchange", () => {
    console.log(document.fullscreenElement);
});

2. 页面可见性 API

js
document.addEventListener("visibilitychange", () => {
    if (document.hidden) {
        console.log("页面隐藏,暂停动画或轮询");
    } else {
        console.log("页面可见,恢复");
    }
});

总结

类别核心 API / 概念
DOM 事件事件流(捕获/冒泡)、委托、CustomEvent、MutationObserver、IntersectionObserver、ResizeObserver
BOMhistory (SPA)、navigator、screen、location 精细操作
图形Canvas 2D、WebGL (Three.js 等)
存储localStorage/sessionStorage、IndexedDB、Cookies (SameSite/Secure/HttpOnly)
网络请求fetch (拦截、中止、流)、XHR (进度监听)、WebSocket、SSE
多线程Web Worker、Shared Worker、Service Worker、SharedArrayBuffer + Atomics
剪贴板navigator.clipboard (readText/writeText)
其他全屏 API、页面可见性 API

生产项目须关注 API 兼容性(查 MDN 兼容性表)与 HTTPS 等安全要求(如 Service Worker)。

参考文献

以下链接在编写时均可正常访问:

资料说明
MDN:Document Object ModelDOM
MDN:事件事件对象
MDN:fetch网络请求
MDN:Web WorkersWorker
MDN:Intersection Observer交叉观察器
MDN:StoragelocalStorage 等

Series

js

5 / 14