Skip to content

7.5 源代码面板(Sources)

源代码面板,顾名思义就是显示当前网页源码的地方。在源代码面板下会显示所有网络请求的资源(按照域名分类),点击某个资源就可以查看该资源源码。源代码面板除了查看资源源码外,另一个主要的功能就是调试,可以帮我们定位到断点或异常出现在源码中的何处。

源代码面板从左到右划分为三个区域:目录区域、源码区域、调试区域,如图 8-25 所示。

7.5.1 操作网页源码

在目录区域的第一个选项卡“网页”下,源代码按照域名分类。我们可以看到顶层的 top 目录和下面包含的当前域名目录,还有与当前域名目录平级的其他目录。

top 目录表示顶层资源,代表一个 HTML 框架,其他资源均在该目录下。top 下的第一个子目录就是当前域名目录,该目录下存放当前网站的源码,我们称之为源码目录(如图中的 cn.vuejs.org 目录)。

源码目录下会按照网页请求资源的 URL 自动划分子目录,展示出来的目录结构几乎与源码目录结构一致。当然对于使用构建工具打包过的项目,这里的目录结构与项目构建后的目录结构匹配。展开目录找到某个资源(图片、CSS、JavaScript),点击即可打开。

  1. 编辑源码

打开 CSS 或 JavaScript 代码后,在源码区域可以查看并编辑这些代码,更改后 DevTools 会运行新代码并更新页面。例如我们修改了某个元素的背景色,会在页面中看到更改立即生效。

CSS 更改立即生效,无需保存。JavaScript 更改后需要按 Command+S (Mac) 或 Control+S(Windows)保存后生效。DevTools 不会重新运行整个脚本,只会对修改过的部分重新执行。

编辑源码只对当前页面生效。如果刷新页面,所有修改过的内容都会被清除。

  1. 运行代码片段

运行代码片段是指将一段 JavaScript 代码交给当前页面运行,查看页面运行后的结果。假设我要给当前页面插入一个 jQuery 引入,代码片段如下:

js
let script = document.createElement("script");
script.src = "https://code.jquery.com/jquery-3.2.1.min.js";
document.head.appendChild(script);

将该片段直接在控制台中运行,结果符合预期。如果有很多这样的脚本需要在多个页面测试,控制台粘贴的方式就会很不方便。高效的方法是将其保存为一个代码段,在任何页面点击一下即可运行。

目录区域切换到“代码段”选项卡,点击新建代码段,创建一个名称并编写代码,然后点击运行。如图 8-27 所示。

该代码片段会保存在磁盘中,刷新页面、关闭浏览器也不会丢失。任何页面需要调试某个代码段,只需要点击运行即可。

7.5.2 断点调试

如果你一直在使用 console.log() 的方式调试代码,不如试试更高效的断点调试。“打断点”的方式很简单,在 JavaScript 代码中添加一个 debuger,或者在源码面板中找到某行代码,点击行号,即可设置一个断点,如图 8-28 所示。

在上图中,当代码运行到断点处时会暂停执行,并在源码面板中自动定位到断点对应的行号。在断点之前定义或使用的任意属性和变量,可以直接查看、或者将鼠标悬停到变量上面预览变量值,这比 console.log()更简单直观。

  1. 处理断点

在一个 JavaScript 脚本中可以添加多个断点,当遇到第一个断点暂停时,我们可以选择如何处理该断点。处理断点有多种方式,在调试区域的第一行有多个处理断点的按钮,如图 8-29 所示。

上图中一共七个按钮,按照顺序每个按钮对应的含义如下:

  • 跳过断点。
  • 跳过函数。
  • 进入函数。
  • 跳出函数。
  • 单步调试。
  • 停用断点。
  • 异常暂停。
  1. 跳过断点

当遇到断点并查看变量后,我们确定了当前位置是否有问题,那么下一步的通常做法是跳过当前断点,继续执行代码。点击跳过断点按钮会跳过当前断点,继续执行脚本。

如果有多个断点,点击后会进入下一个断点,多次点击直到跳过全部断点。如果在某个断点暂停后,我们想查看其后面的某个变量值,那么请点击这行代码最前面的行号创建一个新的断点。继续点击跳过断点按钮,就会在新建的这个断点处暂停。

  1. 跳过/进入/跳出函数

当断点的后面有一个函数调用时,我们可以选择跳过或进入这个函数。

跳过函数相当于在函数调用的位置新添加了一个断点,会自动在函数调用的位置暂停,不需要手动添加 debugger。当点击跳过函数时,该函数执行;如果有多个函数时,断点会停到下一个函数调用的位置,连续点击会逐一跳过多个函数。

当断点暂停到某个函数调用时,点击进入函数按钮,断点会进入函数内部,连续点击会在函数内部逐行暂停。如果函数内部还有其他函数,那么你可以继续选择跳过或进入这个函数。

如果当前断点已进入函数内部的某个位置,我们不想继续调试后面的代码,可以直接点击跳出函数,此时断点会跳出到函数的外面,继续执行函数外的调试。

注意:点击跳过/进入函数时,普通函数只会在函数调用的位置停止,箭头函数则在函数声明、函数调用的位置都会停止。但只有在函数调用的位置上点击进入函数,断点才能进入函数内部。

  1. 单步调试

单步调试很简单,就是按照代码执行顺序一行一行地暂停,直到代码执行完毕。虽然单步调试逐行暂停的效率比较低,但是在一些复杂逻辑的部分,逐行暂停代码可以更细致地排查错误。

  1. 停用断点

停用断点,就是停止执行代码中所有的断点。停用断点默认不开启,点击开启后所有的断点失效。

  1. 异常暂停

异常暂停是指在页面中发生代码异常后,会在异常的部分自动打断点,显然调试异常时使用这种方式更便捷。

7.5.3 作用域、调用栈、事件监听

当代码在断点处暂停时,可以直接在调试区域看到代码执行时的作用域数据和函数调用栈等一系列信息,这些信息为我们提供了更全面的调试方式。下面我们介绍调试区域常用的三处高级调试。

  1. 作用域数据

展开图中的“作用域”标签,可以看到有本地和代码块的数据。本地数据是函数作用域内定义的状态,代码块则是当前 JavaScript 脚本内定义的状态。不管看哪个状态,你都会找到熟悉的变量,并看到它们的值。

双击某条数据,可以进入输入框修改数据值,保存后点击跳过断点,后面的代码逻辑会按照修改后的值执行,这样调试不同数据的效果时非常高效。

  1. 函数调用栈

展开图中的“调用堆栈”标签,即可看到当前断点处的函数调用关系。最上层的是栈顶(最后调用)的函数,往下依次排列,setup 表示全局模块,可以看作是脚本的初始化执行。

假设一个 JavaScript 文件代码如下,将其执行:

js
const fun1 = () => {
  console.log(1);
  debugger;
};
const fun2 = () => {
  console.log(2);
  fun1();
};
const fun3 = () => {
  console.log(3);
  fun2();
};
fun3();

断点处查看函数调用栈如图 8-30 所示。

  1. 全局事件监听

事件监听器断点将几乎所有事件全部罗列了出来,每个事件前都有一个复选框,选中后即可全局监听该事件,如图 8-31 所示。

图中我们选中了 XHR 的 error 和 timeout 事件。这样当页面中存在网络请求失败时,请求异常的位置会被自动打上断点,这样我们调试请求异常就会非常高效,其他浏览器事件亦是如此。