2、前端调试技巧:断点调试(Breakpoints)、条件断点、DOM断点、事件监听器断点、XHR/Fetch断点
调试,说白了就是给代码看病。你写了一大段逻辑,结果页面白屏了,或者数据死活不对。这时候怎么办?console.log 打满天下?我以前也这么干,直到有一次在线上环境忘了删 log,把用户控制台刷成了瀑布流……嗯,从那以后我老老实实学断点。
断点调试是 Chrome DevTools 里最核心的技能。我敢说,你把这五种断点玩熟了,至少能省下一半的排查时间。咱们一个一个来。
2.1 基础断点(Breakpoints)
这是最基础的,也是你最先要掌握的。在 Sources 面板里,找到你要调试的 JS 文件,点击行号左侧,就会出现一个蓝色箭头。这就是断点。
页面运行到这一行时,会自动暂停。你可以看到当前所有变量的值,也可以一步步往下走。
核心操作:
- F8:继续执行,直到下一个断点
- F10:单步跳过,不进入函数内部
- F11:单步进入,会钻进函数里看细节
- Shift + F11:跳出当前函数
我个人习惯是:先大致定位问题区域,打一个断点。然后按 F10 快速过一遍流程。如果发现某个函数返回值不对劲,再按 F11 钻进去看。
小技巧: 你可以在断点上右键,选择「Edit breakpoint」。这里可以写一个表达式,只有表达式为 true 时才会暂停。比如你只关心循环到第 10 次的情况,就写 i === 10。
2.2 条件断点(Conditional Breakpoints)
这个太实用了。你想想看,一个 for 循环跑了 1000 次,你总不能每次都停下来看吧?
右键点击行号,选择「Add conditional breakpoint」。输入条件表达式,比如 user.id === 1024。只有满足条件时,代码才会暂停。
// 假设你在调试这段代码
for (let i = 0; i < users.length; i++) {
const user = users[i];
// 在这里打条件断点:user.role === 'admin'
processUser(user);
}
我在项目中遇到过一个问题:某个用户的数据总是渲染异常,但其他用户都正常。用条件断点直接定位到那个用户的 ID,一下子就看到了数据格式的差异。比一条条 log 翻效率高太多了。
注意: 条件表达式里不要写太复杂的逻辑,也不要调用异步函数。否则调试器会卡住,甚至导致页面崩溃。我曾经写了个 await fetch() 进去……嗯,页面直接挂了。
2.3 DOM 断点(DOM Breakpoints)
这个断点不是打在 JS 代码上的,而是打在 DOM 元素上的。你想想看,有时候页面上的某个元素突然消失了,或者样式被改了,你根本不知道是哪段代码干的。
在 Elements 面板里,选中你要监控的元素,右键 → Break on → 选择一种类型:
| 类型 | 触发时机 | 适用场景 |
|---|---|---|
| Subtree modifications | 子节点被增删改时 | 列表项被动态添加或移除 |
| Attribute modifications | 元素的属性(如 class、style)被修改时 | 某个元素的样式突然变了 |
| Node removal | 元素本身被移除时 | 元素莫名其妙消失了 |
我记得有一次,一个弹窗组件在点击后总是闪一下就消失。我怀疑是某个定时器把它移除了,但翻遍代码都找不到。最后用 DOM 断点监控了弹窗的 Node removal,一触发就直接定位到了罪魁祸首——一个清理函数被错误地绑定了两次。
建议: DOM 断点特别适合排查「谁动了我的元素」这类问题。配合 Call Stack 面板,你能看到完整的调用链,包括是哪个事件触发的、哪个函数执行的。
2.4 事件监听器断点(Event Listener Breakpoints)
这个功能在 Sources 面板的右侧。点开「Event Listener Breakpoints」,你会看到一长串事件类型:click、mouseover、scroll、keydown……
勾选某个事件后,只要页面上有任何代码触发了这个事件,调试器就会自动暂停。注意,是所有代码,包括第三方库的。
举个例子:你发现点击某个按钮后,页面跳转了。但你找不到是哪个事件绑定的。勾选 click 事件断点,然后点击按钮。调试器会停在触发 click 的那一行代码上。你就能看到是哪个函数在处理这个点击。
常用场景:
- 排查点击事件冒泡导致的意外行为
- 定位第三方库中的事件绑定
- 检查键盘快捷键是否被正确触发
我个人习惯是:先勾选所有鼠标事件,然后快速操作页面。如果某个操作触发了断点,再缩小范围到具体的事件类型。这样能快速找到「谁在监听我的操作」。
2.5 XHR / Fetch 断点(XHR/Fetch Breakpoints)
这个断点专门用来调试网络请求。在 Sources 面板右侧,找到「XHR/Fetch Breakpoints」。点击加号,输入一个 URL 关键字。
比如你输入 /api/user,那么所有包含这个关键字的请求(无论是 XHR 还是 Fetch)都会触发断点。调试器会停在发起请求的那一行代码上。
// 假设你在调试这段代码
fetch('/api/user/profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: 1024 })
})
.then(res => res.json())
.then(data => {
// 你想看看 data 到底是什么
});
在断点触发时,你可以查看请求的 headers、body,以及后续的响应数据。我经常用它来排查「请求发了但没收到响应」或者「响应数据格式不对」的问题。
避坑指南: 我曾经在调试时输入了 / 作为关键字,结果所有请求都触发了断点……页面直接卡死。建议关键字尽量精确,比如具体的接口路径或参数名。
2.6 综合实战:一个真实场景
假设你遇到一个问题:用户点击「提交订单」按钮后,页面没有任何反应。控制台也没有报错。你怎么排查?
- 先打事件监听器断点:勾选 click 事件。点击按钮,看看到底有没有触发 click。
- 如果触发了:在 Sources 里找到对应的处理函数,打一个基础断点。按 F10 一步步走,看逻辑走到哪一步停了。
- 如果没触发:可能是按钮被禁用了,或者被其他元素遮挡了。用 DOM 断点监控按钮的 attribute modifications,看谁改了它的 disabled 属性。
- 如果请求没发出去:在 XHR/Fetch 断点里加上接口关键字。点击按钮,看请求是否被发起。如果没发起,说明请求代码根本没执行到。
- 如果请求发了但没响应:在 Network 面板里看请求详情。状态码、响应体、请求头,一个一个排查。
你看,这五种断点组合起来,几乎能覆盖前端调试的 90% 场景。不用再靠 console.log 瞎猜了。
最后说一句: 调试不是找 bug,而是理解代码的运行过程。断点让你能「慢放」代码的执行,看到每一帧的状态。多用几次,你会爱上这种感觉的。