DevTools 打开方式 & 全局快捷键
工欲善其事,必先利其器。掌握快捷打开方式是高效调试的第一步。
常用打开方式
1
快捷键打开 — Mac: Cmd + Option + I | Windows: F12
2
元素选择模式 — Mac: Cmd + Shift + C | Windows: Ctrl + Shift + C,直接进入页面元素选取
3
直接打开 Console — Mac: Cmd + Option + J | Windows: Ctrl + Shift + J
4
右键菜单 — 页面任意位置右键 → "检查"(Inspect),自动定位到对应元素
5
浏览器菜单 — Chrome 菜单 → 更多工具 → 开发者工具
Dock 位置切换
DevTools 打开后,可以点击右上角的 三点菜单 或按 Cmd + Shift + D 切换停靠位置:
底部 Dock
↔
右侧 Dock
↔
左侧 Dock
↔
独立窗口
Tip: 宽屏推荐右侧 Dock,排查移动端问题时推荐独立窗口 + 设备模拟。
Settings 设置
按 F1 或 Cmd + , 打开 DevTools Settings:
- Preferences — 主题(Dark/Light)、字体大小、默认面板
- Workspace — 映射本地文件夹实现持久化修改
- Experiments — 实验性功能(如 CSS Overview 面板)
- Ignore List — 调试时忽略第三方库代码(如 node_modules)
- Throttling — 自定义网络节流配置
- Devices — 自定义设备模拟分辨率
Tip: 推荐在 Settings → Preferences 中开启 "Auto-open DevTools for popups",调试弹窗时不再错过时机。
全局快捷键速查
| 操作 | Mac | Windows / Linux |
| 打开 / 关闭 DevTools | Cmd + Option + I | F12 |
| 打开 Console 面板 | Cmd + Option + J | Ctrl + Shift + J |
| 元素选择模式 | Cmd + Shift + C | Ctrl + Shift + C |
| 设备模拟模式 | Cmd + Shift + M | Ctrl + Shift + M |
| 快速切换 Dock 位置 | Cmd + Shift + D | Ctrl + Shift + D |
| 搜索当前面板 | Cmd + F | Ctrl + F |
| 全局搜索所有文件 | Cmd + Option + F | Ctrl + Shift + F |
| 命令菜单 (Command Menu) | Cmd + Shift + P | Ctrl + Shift + P |
| 切换面板标签(左右) | Cmd + ] / Cmd + [ | Ctrl + ] / Ctrl + [ |
类比理解:DevTools 就像是浏览器的"X光机",让你透视页面的骨骼(DOM)、皮肤(CSS)、神经系统(JS)、血液循环(Network),每一个面板都是一个专业科室。
Elements 面板 — DOM & CSS 调试
前端调试最常用的面板,实时查看和修改 DOM 结构与 CSS 样式。
DOM 树操作
| 操作 | 方法 | 说明 |
| 展开 / 折叠节点 | 点击节点左箭头或双击标签 | 展开子树,也可用右方向键展开、左方向键折叠 |
| 搜索 DOM | Cmd + F | 按标签名、类名、文本内容搜索,支持 CSS 选择器和 XPath |
| 复制选择器 | 右键 → Copy → Copy selector | 生成唯一的 CSS 选择器路径,如 #app > div > ul > li:nth-child(3) |
| 复制 JS 路径 | 右键 → Copy → Copy JS path | 生成可直接在 Console 中使用的 DOM 访问代码 |
| 滚动到视图中 | 右键 → Scroll into view | 快速定位页面中隐藏或不在视口的元素 |
| 删除节点 | 右键 → Delete element 或 Delete 键 | 即时移除 DOM 节点,可按 Cmd + Z 撤销 |
| 强制状态 | 点击 .hov 按钮 | 模拟 :hover / :focus / :active / :visited / :focus-within |
| 拖拽移动 | 拖拽节点到新位置 | 实时调整 DOM 顺序,排查布局问题 |
| 编辑属性 | 双击属性名 / 属性值 / 文本 | 直接修改 class、id、内联文本等 |
| 以 HTML 编辑 | 右键 → Edit as HTML | 批量编辑整个节点的 HTML |
Tip: 选中节点后按 H 键可以快速切换元素的 visibility: hidden,按 Delete 键删除节点,Cmd + Z 可撤销任何 DOM 操作。
样式面板详解
Styles 面板
- 按 CSS 优先级从高到低 显示所有匹配规则
- 每条规则旁标注 文件名 + 行号,点击可跳转到 Sources 面板对应位置
- 被划线的属性 = 不生效(被更高优先级覆盖或属性无效)
- 点击属性值可用 上下方向键 微调数值(+1 / -1),按住 Shift 步进 ±10,按住 Alt 步进 ±0.1
- 点击颜色值弹出 颜色选择器,支持取色、HSL/HEX/RGBA 切换
- element.style 区域可直接添加内联样式
- 点击右上角 +.cls 按钮可以添加/移除 class
/* Styles 面板中显示示例 */
/* styles.css:42 */ ← 文件来源 + 行号
.card-title {
font-size: 16px; ← 生效
color: red; ← 划线 = 被覆盖
color: blue; ← 不生效
}
/* element.style */ ← 内联样式(最高优先级之一)
font-weight: bold;
Computed 面板
- 显示每个 CSS 属性的 最终计算值(浏览器最终渲染使用的值)
- 如 font-size: 2em 在 Computed 中显示为实际像素值,如 32px
- 点击任意属性可展开查看 所有来源及优先级,标明哪个规则最终胜出
- 勾选 "Show all" 可查看所有 CSS 属性(包括继承的默认值)
Box Model 可视化
- 在 Styles 下方或 Computed 面板顶部展示 盒模型图
- 由外到内:Margin → Border → Padding → Content
- 上、右、下、左四个数值均可 直接点击编辑
- 非常直观地排查元素的实际占用空间
CSS 变量 & 主题调试
CSS 自定义属性(变量)在 Styles 面板中可以直接查看和修改:
/* CSS 变量定义 */
:root {
--primary-color: #B4B8F0;
--font-size-base: 14px;
}
/* 使用处 */
.card {
color: var(--primary-color);
font-size: var(--font-size-base);
}
在 Styles 面板中悬停变量名会显示当前值,点击可跳转到定义位置。直接修改变量值可实时看到全局效果 — 非常适合调试主题色和设计系统。
实战场景
场景 1:样式不生效排查
当你写了 CSS 但页面没有变化时,按以下流程排查:
1
选中目标元素,在 Styles 面板查看是否有你写的规则
2
如果规则存在但属性被 划线 → 被更高优先级覆盖,检查是否有 !important 或更具体的选择器
3
如果规则 根本不存在 → 选择器不匹配(class 名拼写错误、DOM 结构与选择器不一致)
4
切到 Computed 面板,搜索目标属性,查看哪个规则最终胜出
常见陷阱:
- !important 滥用导致样式覆盖混乱
- CSS 特异性(Specificity)计算错误:#id > .class > tag
- 样式文件未正确加载 — 检查 Network 面板是否 404
- CSS 属性拼写错误,如 collor 不会报错只是静默失效
场景 2:响应式调试
1
按 Cmd + Shift + M 进入设备模拟模式
2
在顶部工具栏选择预设设备(iPhone、iPad 等)或自定义分辨率
3
拖动视口宽度边缘或输入数值,实时查看布局变化
4
在 Styles 面板中查看 媒体查询断点(灰色 @media 标记)
Tip: 点击 Styles 面板上方的媒体查询栏(彩色竖条),可以快速跳转到对应断点宽度。右键媒体查询条可以选择跳转到 CSS 源码。
类比理解:Elements 面板就像装修师傅的工具箱 — DOM 树是房屋结构图,Styles 面板是色卡和材料清单,Box Model 是量尺。你可以随时换壁纸(CSS)、移家具(DOM)、量尺寸(Computed),所见即所得。
Console 面板 — 报错 & 日志
前端排错的第一道防线。读懂 Console 的红色报错,你就解决了 50% 的问题。
报错类型识别
| 级别 | 颜色 | 常见类型 | 含义 |
| Error |
红色 |
SyntaxError |
语法错误 — 代码写法有问题,如缺少括号、拼写错误 |
|
|
ReferenceError |
引用错误 — 使用了未声明的变量或函数 |
|
|
TypeError |
类型错误 — 对 null/undefined 调用方法,或参数类型不对 |
|
|
RangeError |
范围错误 — 如递归爆栈、无效数组长度 |
| Warning |
黄色 |
Deprecated API |
使用了即将废弃的 API,建议迁移 |
| Info |
蓝色 |
console.info() |
信息提示 |
| Log |
白色 |
console.log() |
普通日志 |
如何阅读错误信息:
Uncaught TypeError: Cannot read properties of undefined (reading 'map')
at UserList (UserList.js:23:18)
at renderWithHooks (react-dom.js:16185:18)
at mountIndeterminateComponent (react-dom.js:18342:5)
拆解:
- TypeError — 错误类型
- Cannot read properties of undefined (reading 'map') — 试图对 undefined 调用 .map()
- UserList.js:23:18 — 出错文件 + 行号 + 列号,点击可直接跳转
- 堆栈 — 从上到下是调用链,最上面是出错位置,下面是调用者
Console 技巧大全
console 方法
// 基本输出
console.log('普通日志');
console.warn('⚠ 警告信息');
console.error('❌ 错误信息');
console.info('ℹ 提示信息');
// 表格输出 — 数组/对象的最佳展示方式
console.table([
{ name: '张三', age: 25, city: '北京' },
{ name: '李四', age: 30, city: '上海' },
]);
// 分组输出
console.group('用户信息');
console.log('姓名: 张三');
console.log('年龄: 25');
console.groupEnd();
// 计时 — 性能分析利器
console.time('API请求耗时');
await fetch('/api/users');
console.timeEnd('API请求耗时'); // 输出: API请求耗时: 234ms
// 计数
for (let i = 0; i < 5; i++) {
console.count('循环次数'); // 循环次数: 1, 2, 3, 4, 5
}
// 断言 — 条件为 false 时才输出
console.assert(user.age > 0, '年龄必须大于0');
// 清屏
console.clear();
Console 内置快捷变量和函数
| 命令 | 功能 | 示例 |
| $0 | 当前 Elements 面板选中的元素 | $0.classList |
| $1 ~ $4 | 历史选中的前几个元素 | $1 = 上一个选中的 |
| $(selector) | 等价 document.querySelector | $('.card') |
| $$(selector) | 等价 document.querySelectorAll(返回数组) | $$('li') |
| copy(obj) | 复制到剪贴板 | copy($0.outerHTML) |
| keys(obj) | 返回对象自身可枚举属性名 | keys(localStorage) |
| values(obj) | 返回对象自身可枚举属性值 | values({a:1,b:2}) |
| monitor(fn) | 监控函数调用及参数 | monitor(fetch) |
| debug(fn) | 调用函数时自动断点 | debug(handleClick) |
过滤与搜索
- 按级别过滤:点击 Console 左上角的 Levels 按钮勾选 Verbose / Info / Warnings / Errors
- 按文字搜索:在过滤框输入关键词
- 正则过滤:输入 /pattern/ 格式的正则表达式
- 排除过滤:输入 -pattern 排除包含该文字的日志
实用操作
- 清屏: Cmd + K 或点击 🚫 按钮
- Preserve Log: 勾选后页面刷新/跳转不会丢失日志
- Selected Context Only: 只显示当前选中 iframe 的日志
- 右键日志 → Save as: 导出所有日志为文件
- 右键日志 → Store as global variable: 保存为临时变量 temp1
Tip: console.log 输出对象时是引用类型!展开看到的值可能是 之后修改过的。需要快照时使用 console.log(JSON.parse(JSON.stringify(obj)))。
实战场景
场景 1:接口 404
Console 显示红色错误:
GET https://api.example.com/ussers 404 (Not Found)
1
注意 URL 中 ussers 拼写错误(应为 users)
2
点击错误信息中的链接,自动跳转到 Network 面板对应请求
3
在 Network 面板查看 Response,确认 404 详情
场景 2:undefined 变量 — ReferenceError
Uncaught ReferenceError: userData is not defined
at renderProfile (profile.js:15:22)
at <anonymous>:1:1
1
点击 profile.js:15:22 跳转到源码
2
检查第 15 行附近,发现变量名拼写错误或未导入
3
在 Console 中输入 userData 确认当前作用域是否存在
场景 3:CORS 跨域报错
Access to fetch at 'https://api.other.com/data' from origin 'https://myapp.com'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is
present on the requested resource.
排查步骤:
- 这是 服务端问题,前端无法直接解决
- 需要后端在 Response Headers 中添加 Access-Control-Allow-Origin
- 开发环境可通过代理(如 webpack devServer proxy)绕过
- 在 Network 面板中可以看到请求发出了但响应被浏览器拦截
类比理解:Console 就像是汽车的仪表盘和故障指示灯。红色 Error 是引擎故障灯,黄色 Warning 是保养提醒,普通 Log 是行驶记录。学会看仪表盘,你就能快速定位问题。
Network 面板 — 网络请求全链路
前端排错的核心面板!接口调试、性能分析、资源加载排查都离不开它。这是面试高频考点。
重要提示:打开 Network 面板后 不会 显示之前的请求!必须先打开面板,再刷新页面或操作。勾选 "Preserve log" 可以在页面跳转时保留日志。
请求列表详解
| 列名 | 含义 | 重点关注 |
| Name | 请求的 URL 路径和文件名 | 点击可查看详情 |
| Status | HTTP 状态码 | 200 成功 / 301 重定向 / 404 未找到 / 500 服务器错误 |
| Type | 资源类型 | document / script / stylesheet / xhr / fetch / img / font |
| Initiator | 请求的发起者 | 哪个 JS 文件/哪行代码发起的,排查重复请求利器 |
| Size | 响应大小 | 实际大小 vs 传输大小(gzip 压缩后) |
| Time | 总耗时 | 从请求发出到响应完成的时间 |
| Waterfall | 时间瀑布图 | 可视化各请求的加载时序和并行情况 |
筛选与搜索
类型筛选按钮
All
XHR
JS
CSS
Img
Doc
Font
WS
属性过滤(Filter 输入框)
# 按状态码过滤
status-code:404
status-code:200
# 按大小过滤
larger-than:1M
larger-than:100k
# 按请求方法过滤
method:POST
method:GET
# 按域名过滤
domain:api.example.com
# 按 MIME 类型过滤
mime-type:application/json
# 组合使用
method:POST status-code:500
Tip: 按 Cmd + F 打开搜索框,可以搜索请求和响应中的内容(如在所有响应中搜索某个字段值)。
请求详情(点击请求后)
Headers 标签页
┌─ General ──────────────────────────────────┐
│ Request URL: https://api.example.com/users │
│ Request Method: GET │
│ Status Code: 200 OK │
│ Remote Address: 93.184.216.34:443 │
│ Referrer Policy: strict-origin-when-origin │
└────────────────────────────────────────────┘
┌─ Response Headers ─────────────────────────┐
│ Content-Type: application/json │
│ Access-Control-Allow-Origin: * │
│ Set-Cookie: token=abc123; HttpOnly; Secure │
│ Cache-Control: max-age=3600 │
└────────────────────────────────────────────┘
┌─ Request Headers ──────────────────────────┐
│ Cookie: session_id=xyz789 │
│ Authorization: Bearer eyJhbG... │
│ Content-Type: application/json │
│ User-Agent: Mozilla/5.0 ... │
└────────────────────────────────────────────┘
┌─ Query String Parameters ──────────────────┐
│ page: 1 │
│ pageSize: 20 │
│ keyword: "张三" │
└────────────────────────────────────────────┘
关键看点:
- General 中的 Status Code:快速判断请求成败
- Request Headers 中的 Cookie / Authorization:排查鉴权问题
- Response Headers 中的 Set-Cookie / CORS 头:排查跨域和 Cookie 问题
- Query String Parameters:确认 GET 请求的参数是否正确
Payload 标签页
查看请求发送的数据:
- Query String Parameters — URL 中的查询参数
- Form Data — 表单提交的数据(Content-Type: application/x-www-form-urlencoded)
- Request Payload — JSON 格式的请求体(Content-Type: application/json)
Tip: 查看 Payload 是排查"后端说没收到参数"的标准流程 — 先确认前端到底发了什么。
Preview / Response 标签页
- Preview — 格式化展示:JSON 会美化显示成可折叠的树结构,图片会显示预览
- Response — 原始响应文本,可复制完整内容
Timing 时序分析(重点!)
点击请求 → Timing 标签页,查看请求各阶段耗时:
Stalled
浏览器等待分配连接的时间(连接池满/排队)
DNS Lookup
DNS 解析域名到 IP 地址。首次访问较慢,之后有缓存
Initial Connection
建立 TCP 连接。复用连接时为 0
SSL
TLS/SSL 握手时间(HTTPS 请求)
Request Sent
发送请求报文的时间。通常很短
Waiting (TTFB)
Time To First Byte — 等待服务器返回第一个字节。TTFB 高 = 服务端慢
Content Download
下载响应体的时间。大 = 资源体积大或带宽低
瓶颈判断指南:
- TTFB 过长(>1s):服务端处理慢 — 检查后端日志、数据库查询、服务端渲染
- Content Download 过长:响应体太大 — 开启 gzip/brotli 压缩、分页、减少返回字段
- Stalled 过长:浏览器并发限制(同域最多 6 个连接)— 使用 CDN、HTTP/2 多路复用
- DNS Lookup 过长:DNS 解析慢 — 使用 dns-prefetch
- SSL 过长:TLS 握手慢 — 考虑 OCSP Stapling、使用 CDN
Initiator 发起者
点击请求 → Initiator 标签页,查看请求的 完整调用栈:
Initiator:
fetchData @ api.js:42
loadUserList @ UserList.js:18
useEffect @ UserList.js:10
react @ react-dom.js:16185
mountComponent @ react-dom.js:18342
从下往上看调用链,定位到 你自己的代码 中的发起位置。非常有助于排查:
- 重复请求(某个组件重复渲染导致多发了一次请求)
- 非预期的请求(不知道哪个组件触发的)
- 请求顺序问题
实战场景
场景 1:接口 500 — 服务端错误
1
Network 列表中找到 500 状态码的请求(红色高亮)
2
点击 → Response 标签页查看服务端返回的错误信息
3
切到 Payload 标签页确认发送的参数是否正确(字段名、格式、值)
4
携带 Response 错误信息 + Payload 参数 → 反馈给后端同学
场景 2:页面加载慢 — Waterfall + Timing 分析
1
打开 Network,勾选 "Disable cache",刷新页面
2
查看 Waterfall 瀑布图,找到耗时最长的请求(按 Time 排序)
3
点击最慢的请求 → Timing 分析瓶颈环节
4
检查是否有资源阻塞渲染(长条排在关键资源前面)
5
底部状态栏查看总请求数、总传输大小、总加载时间(DOMContentLoaded 和 Load 时间)
场景 3:重复请求 — Initiator 定位代码
1
在 Network 中发现同一个接口被调用了多次
2
点击重复请求 → 查看 Initiator 调用栈
3
在调用栈中找到你自己的代码位置(跳过框架代码)
4
常见原因:React 组件重复渲染(useEffect 缺少依赖/未做 memo)、事件重复绑定
场景 4:Cookie 问题 — 登录态丢失
1
在 Network 中找到返回 401 的请求
2
检查 Request Headers 中是否有 Cookie 字段
3
如果没有 Cookie → 检查 Set-Cookie 的 Domain、Path、SameSite、Secure 属性
4
常见原因:跨域请求未携带 Cookie(需设置 credentials: 'include' + CORS 头)
类比理解:Network 面板就像是快递追踪系统。每个请求是一个包裹,Status 是签收状态,Timing 是各中转站耗时,Waterfall 是所有包裹的物流时间线,Initiator 是寄件人的详细信息。