Chrome 开发者工具是内置于谷歌浏览器中 web 开发调试工具,对于网页的调试、分析等特别有帮助。了解这些工具的使用,可以提高我们前端的开发效率。
打开 DevTools
右击网页,选择【检查】:
也可以使用以下快捷键打开 DevTools:
| 访问 DevTools | 快捷键 |
|---|---|
| 打开 Developer Tools | F12 或者 Ctrl + Shift + I |
| 打开 / 切换 检测元素模式和浏览器窗口 | Ctrl + Shift + C |
| 打开 Developer Tools 并聚焦到控制台 | Ctrl + Shift + J |
Elements
Element: 元素面板,可以操作 DOM 和 CSS。
- Styles:可以新增、修改、删除样式,并立即在页面上反应
- Computed: 展示 box 模型,以及计算过的样式
- Layout:布局
- Event Listeners:Ancestors 取消勾选后,只展示当前选中元素上的监听事件,勾选则展示当前元素及其父级元素上的监听事件
- DOM Breakpoints:DOM 断点
- Properties:展示选中的元素作为 js 对象的 Properties 和方法
(1)编辑 DOM 和 CSS
在这个面板可以编辑 DOM 节点以及属性:
编辑及创建 CSS 样式:
长按拖拽移动元素,选中 + Delete 删除元素,或者选中元素右击:
(2)DOM 断点
选中元素右击,选择【Break on】:
- subtree modifications:子树修改,当一个子元素添加,删除或移动时,将会触发子树修改断点
- attribute modifications:属性修改,当元素的属性(class,id,name)动态发生变化时,会出现属性修改
- node removal:节点移除,当问题提及的节点从 DOM 中移除时,将触发节点移除修改
当元素出现 即为断点设置成功,右边 DOM Breakpoints 会列出当前元素所有的 DOM 断点
(3)元素事件监听器
选中元素切换到 Event Listeners,点击元素标识符左边的展开箭头以查看事件处理器的属性:
事件监听器为每个监听器列出了以下属性:
- useCapture:一个布尔值,表示是否已设置 addEventListener 中的 useCapture 标志。
- Passive:是否是被动触发
- Once:是否只触发一次
- handler:包含回调方法。右键点击方法并选择 Show Function Definition 来查看该方法定义的地方。(如果源代码可用的话)
Console
Console: 控制台面板,命令行交互
(1)控制台API
控制台 API 为 Web 应用程序提供输入信息到控制台、创建 JavaScript 文件和启动调试会话的方法。
1)console.assert(expresson,object):如果指定表达式返回 false,返回结果会随着一个栈跟踪器输入到控制台上。
// 例:数组中是否有小于 10 的数
const minNumber = Math.min(...array);
console.log('array=', array); // [22, 59, 3, 61, 79, 54, 29, 21, 71, 24]
console.assert(minNumber>10, minNumber)
2)console.group(object[, object, ...]):以可选标题项开始一个新的记录组。调用此方法后再调用 console.groupEnd() ,所有控制台输出在同一个视组。
// 例:生成随机数数组
function getArray(length) {
console.group('array start')
let randomArr = [];
for (let i = 0; i < length; i++) {
const item = parseInt(Math.random() * 100);
console.log(item);
randomArr.push(item);
}
console.groupEnd()
return randomArr
}
const array = getArray(10);
3)console.profile([label]):开启一个 JavaScript CPU 状态分析。再调用 console.profileEnd() 停止分析,每个分析结果都会被添加到 Performance 选项卡中。
// 例:1000 个数排序会占用多少 CPU
console.profile('bubbleSort')
bubbleSort(getArray(1000))
console.profileEnd()
4)console.time(label):开始一个新的计时器,与标签关联。当 console.timeEnd() 被调用时,计时器停止计时,在控制台中显示经过时间。
// 例:1000 个数排序需要多少时间
console.time('bubbleSort');
bubbleSort(getArray(1000))
console.timeEnd('bubbleSort');
其他控制台 API:
console.clear():清除控制台console.count(label):在同一个标签被调用的次数console.dir(object):输出指定对象的 JavaScript 的描述。如果被记录的对象是一个 HTML 元素,那么它的 DOM 对象的属性被输出显示console.error(object [, object, ...]):与 console.log() 、console.error() 相似,在该方法被调用的地方同样包括一个栈追踪器console.groupCollapsed(object[, object, ...]):创建一个初始闭合而不是开放的记录组,就像用 console.group()一样console.timeStamp([label]):这个方法在记录期间增加了一个事件到时间轴。这可以让你直观地在时间戳上关联生成的代码到其他事件上,如屏幕布局和绘制,这些都被自动添加到时间轴上。console.trace(object):输出从这个方法被调用的那个点的栈追踪路径,包括在 Javascript 源代码中指向特定行的链接
(2)命令行 API
命令行 API 是 Chrome DevToos 执行常见任务的方法集合。这些集合包含了选择和检查 DOM 元素、停止和启动分析器、监测 DOM 事件的易用方法。命令行 API 仅可在控制台内使用。
1)$_:返回最近一次计算过的表达式的值
2)$0 - $4:$0 返回最近选择的元素或 JavaScript 对象,$1 返回次近选择的一个对象,以此类推
由于浏览器只保留最近 5 次的选中记录,所以 $5 是 undefined
3)$(selector):这个函数是 document.querySelector() 函数的一个别名函数。使用 CSS 选择器返回 DOM 元素的引用
4)table(data[, columns]):通过用可选用的列标题传进一个数据对象进来,以表格的形式输出对象数据。
其他命令行 API:
$$(selector):返回匹配给定 CSS 选择器的元素的数组,该命令等同于调用 document.querySelectorAll() 方法。clear():清除控制台的历史记录copy(object):复制指定对象的字符表示到剪切板getEventListeners(object):返回注册在指定对象上的注册的事件监听器。返回值是一个包含了每个注册事件类型(例如 “click” 或 “keydown”)的数组对象。每个数组的成员都是描述每种类型注册监听器的对象。keys(object):返回一个数组,包含了指定对象属性的名字values(object):返回一个数组,包含了指定对象的所有属性值monitorEvents(object[, events]):当指定的事件之一发生在指定对象上,该事件的对象就被输出到控制台。你可以指定单个事件,到监视器,事件数组,或被映射到通用事件类型中之一,这个集合映射到预定的事件集合unmonitorEvents(object[, events]):停止监视指定的对象和指定事件的事件
Sources
Sources:源面板,允许调试 JavaScript 代码。
左侧面板:
- Page: 当前页面正在使用的代码文件列表
- Overrides: 导入覆盖当前页面文件的文件列表,可以把编辑的内容保存到本地,然后用这个本地文件覆盖线上加载的内容。
在 Elements 面板直接调试样式时,刷新浏览器之后之前修改的样式会全部丢失,这个问题就可以用 Overrides 来解决:
1)在 Overrides 面板里选择保存到本地哪个文件夹里
2)在 Page 里找到要编辑的文件,右键这个文件,选择【Override content】
3)可以看到 Elements 的样式文件链接前多了个图标,现在修改样式之后,点击刷新,之前的修改不会消失了,修改的内容已经保存在本地
- Snippets: 新增代码片段
编写好需要检测的代码,点击右下角的执行按钮,即可执行代码片段
右侧面板
按钮从左至右分别是:
- continue:继续执行代码,直到遇到另一个断点
- step_over:按正常步骤,应该会一行一行的执行相关代码,以便深入探索哪些代码影响着正在更新的变量。如果你的代码中调用了另一个函数,点击此按钮将不会进入该函数,而是直接略过,将焦点留在当前函数上。
- step_into:进入被调用的函数并且调试器将将其执行到该函数定义中的第一行。
- step_out:在已进入一个函数后,单击此按钮将导致函数定义的其余部分的运行,调试器将将其执行到父函数。
- step:仅下一步操作。
- disable-breakpoints:控制断点开/关的按钮。
- watch:变量监听,对加入监听列表的变量进行监听,在该面板的右侧有添加变量和刷新变量列表的按钮。
- Breakpoints:代码断点列表,点击断点前面的复选框可以暂时“去掉/加上”该断点,点击断点可跳转到相应的程序代码处。
- Scope:作用域,可以查看此时局部变量和全局变量的值。
- Call Stack:显示当前断点所处的方法调用栈,从上到下由最新调用处依次往下排列。当我们点击调用栈列表上的任意一处,便会调到相应的位置,方便我们再回头去看看代码。
- XHR Breakpoints:请求断点列表,对达到满足过滤条件的请求进行断点拦截。
- DOM Breakpoints:DOM断点列表,给DOM加断点,在达到规定条件时触发断点,截断javascript的执行并且定位到断点处。
- Global Listener:显示所有绑定到 window 的事件监听器,也可以找到对应的绑定代码。
- Event Listener Breakpoints:可断点的事件监听列表,打开这个列表,可以在监听事件并且在触发该事件时进入断点,调试器会停留在触发事件代码行。
(1)添加断点
Ctrl + P 打开文件搜索,选中需要调试的文件
点击代码行号即可添加断点
代码执行到断点处暂停,光标悬浮在变量上可以看到变量当前值
(2)条件断点
右击蓝色标签会打开一个菜单,选择【Edit breakpoint】
或者,右键点击行号前的空白然后选择【Add conditional breakpoint】
在输入域中,可以输入任何能够返回 true 或者 false 的表达式。当条件返回 true 的时候,断点会中断代码的执行。
(3)logpoint
右键点击行号前的空白然后选择【Add logpoint】
所有可以写在 console.log 里的代码都可以写在这里,可以使用从全局、闭包、到当前作用域的所有可访问变量
当代码执行到 logpoint 处,控制台会输出 log message
(4)XHR 断点
点击 Sources 面板右侧的 XHR Breakpoints 的 Add 按钮,在文本框输入请求 url。如果不输入直接回车就是对所有请求启用断点
(5)事件监听器断点
在 Event Listener Breakpoints 选中需要监听的事件,当事件执行会触发断点
Network
Network: 网络面板,使用 Network 面板记录和分析网络活动
控制器
过滤器
可以按字符串过滤,按类型过滤
时间轴
浏览器加载顺序:
- 解析 HTML 结构
- 加载外部脚本和样式表文件
- 解析并执行脚本代码(部分脚本会阻塞页面的加载)
- DOM 树构建完成(DOMContentLoaded 事件)
- 加载图片等外部文件
- 页面加载完毕(load事件)
DOMContentLoaded 事件在时间轴上用一条蓝色竖线标记
load 事件在时间轴上用一条红色竖线标记
资源内容
默认时间排序,支持点击Time、Size等字段切换排序。
- Name:资源的名称
- Status:HTTP 状态代码
- Type:已请求资源的 MIME 类型
- Initiator:发起请求的对象或进程
- Size:响应头(通常为数百字节)加响应正文(由服务器提供)的组合大小
- Time:从请求开始至在响应中接收到最终字节的总持续时间
- Waterfall:显示所有网络请求的可视瀑布
右击请求,选择【Copy】,可以复制请求信息
- Copy link address:复制资源url到系统剪贴板
- Copy response:复制HTTP响应
- Copy stack trace:复制堆栈信息
- Copy as PowerShell:复制请求 PwoerShell 代码
- Copy as fetch:复制请求 fetch 代码
- Copy as Node.js fetch:复制请求 Node.js fetch 代码
- Copy as cUrl(cmd):复制请求 cUrl 命令代码
- Copy as cUrl(bash):复制请求 cUrl 命令代码
- Copy all as PowerShell:复制所有请求 PwoerShell 代码
- Copy all as fetch:复制所有请求 fetch 代码
- Copy all as Node.js fetch:复制所有请求 Node.js fetch 代码
- Copy all as cUrl(cmd):复制所有请求 cUrl 命令代码
- Copy all as cUrl(bash):复制所有请求 cUrl 命令代码
- Copy All as HAR:复制所有请求 HAR 文件
点击请求可以查看请求详细信息
- Headers:资源的HTTP头
- Payload:请求参数(没有参数时不显示)
- Preview:预览JSON/image/text资源
- Response:资源的HTTP响应头
- Timing:资源的请求生命周期
Performance
Performance: 记录和分析在应用程序运行时的所有活动。
录制一段运行时的时间轴:
- 概览: 主要性能项目的图形化预览,可选择录制的某一个片段,默认为完整的录制片段。
- 性能面板: 展示 概览 中选择的片段的其他指标数据。点击此面板中的内容可进行选择。
- 性能摘要: 展示 性能面板 中选择内容的详情。其中 Summary 选项卡为点选内容的数据总览,不同的点击项目展示的条目有所区别。
定位性能瓶颈
演示 demo 地址:点这里
- 概览面板 CPU 面积图充满色彩表示该时间段 CPU 已达到极限。当看到 CPU 长时间处于最大状态时就需要寻找减少 CPU 工作量的方法。
- 下方 Summary 可以看到 rendering 时间过长,样式计算和布局(重排)占用了大部分时间,考虑优化渲染过程。
- 紫色事件的顶部为红色,那是警告标志。 将鼠标悬停在这些事件上方,可以看到 DevTools 在警告页面可能会被强制自动重排。点击其中一个布局事件可以选择它,在 Summary 窗格中,会看到与此事件有关的详细信息。
- 点击 Layout Forced (update @ forcedsync.html:457) 下面的链接跳转到函数定义。update() 函数是 requestAnimationCallback() 的回调处理程序。 处理程序会根据每个图像的 offsetTop 值计算其 left 属性。 这将强制浏览器立即执行新布局,以便确保其提供正确的值。在每个动画帧期间强制布局是导致页面上出现动画卡顿的原因。
- 从 HTML 文件复制函数定义,并将其粘贴到 DevTools 的 Console 中。删除使用 offsetTop 的语句并取消注释其下面的语句。 完成后,按 Enter。然后重启动画。可以直观地验证现在顺畅多了。
Memory
Memory: 内存面板,项目运行过程中内存情况的解析工具
- Heap snapshot - 用以打印堆快照,堆快照文件显示页面的 javascript 对象和相关 DOM 节点之间的内存分配
- Allocation instrumentation on timeline - 在时间轴上记录内存信息,随着时间变化记录内存信息
- Allocation sampling - 内存信息采样,使用采样的方法记录内存分配。此配置文件类型具有最小的性能开销,可用于长时间运行的操作。它提供了由 javascript 执行堆栈细分的良好近似值分配
内存溢出问题
- 给 button 绑定 click 事件:
document.getElementById("button").addEventListener("click", function () {
let big = new Array(999999);
console.log(big);
});
- 选中【Allocation instrumentation on timeline】,点击 Strat 按钮开始记录内存信息,点击上面代码绑定了 click 事件的按钮,点击结束录制。可以得到下面的内存信息:
- Shallow size: 这是对象自身占用内存的大小。通常只有数组和字符串的 shallow size 比较大
- Retain size: 保留的大小,这是将对象本身连同其无法从 GC 根到达的相关对象一起删除后释放的内存大小
由此可知,当 Retained Size > Shallow Size 则可能存在内存溢出问题。
- 切换到【Containment】,点开【GC roots】,GC 就是 Garbage Collector,垃圾回收,GC root 就是垃圾回收器的对象。由此可见是
console导致内存溢出。
- 将
console.log注释后重新录制内存信息,可以看到 Retained Size、Shallow Size 已经正常。
Application
Application: 内存面板,检查 web 应用加载的所有资源
- Manifest: PWA 所需的 manifest.json 文件,其作用是用来告诉浏览器如何在用户的桌面上 “ 安装 ” 这个 app,及安装后该展示的信息。
- Service Workers: 独立于当前页面的一段运行在浏览器后台进程里的脚本,由于运行在 worker 上下文,因此它不能访问 DOM,不过可以做一些简单的辅助性逻辑处理和离线缓存等。
- Storage: 展示当前浏览器存储信息的一个总览清除各种缓存。
- Local Storage: 显示浏览器的 localStorage 键值对数据,在这个面板中可以执行查看值、双击空行新增 KVP、双击 KVP 对其进行修改、删除 KVP 等操作。
- Session Storage: 显示浏览器的 sessionStorage 键值对数据,在这个面板中可以执行查看值、双击空行新增 KVP、双击 KVP 对其进行修改、删除 KVP 等操作。
- IndexedDB: 浏览器端提供的本地存储键值对的数据库,建立在事务数据库模型上(所做的操作都发生在创建的事务对象上下文),其 api 大多都是异步的。
- Cookies: 查看、新增(仅限)、修改、删除 http cookies。
- Cache Storage: sw 缓存的资源列表。
- Background Fetch: 用于生成在后台挂起的 fetch 资源任务。
- Background Sync: 生成在后台挂起执行的同步任务。
- Frames: 该面板显示了该网站所有内容资源。
浏览器缓存
localStorage.setItem(key, value) :设置浏览器缓存。sessionStorage 使用sessionStorage.setItem(key, value)
const object = {
name: "Tom",
age: "18",
};
const array = [
{
name: "Jerry",
age: "19",
},
{
name: "Alice",
age: "17",
},
];
localStorage.setItem("object", JSON.stringify(object));
localStorage.setItem("array", JSON.stringify(array));
localStorage.setItem("string", "my friend");
Application 查看 localStorage 如下:
点击可查看缓存对象。
注意:数据在存取的时候都必须是
string类型。