浏览器的调试
你的时间有限,所以不要为别人而活。不要被教条所限,不要活在别人的观念里。不要让别人的意见左右自己内心的声音。最重要的是,勇敢的去追随自己的心灵和直觉,只有自己的心灵和直觉才知道你自己的真实想法,其他一切都是次要。你是否已经厌倦了为别人而活?不要犹豫,这是你的生活,你拥有绝对的自主权来决定如何生活,不要被其他人的所作所为所束缚。给自己一个培养自己创造力的机会,不要害怕,不要担心。过自己选择的生活,做自己的老板!
——史蒂夫·乔布斯
这篇文档主要介绍谷歌浏览器的调试工具的使用
# 概述
Chrome 开发者工具 Chrome 开发者工具是一套内置在 Google Chrome 中 Web 开发和调试工具。使用开发者工具来重演,调试和剖析您的网站。
注意:寻找最新版本的 Chrome 开发者工具,Chrome Canary 总是有最新的 DevTools。
# 1.调试工具
Console(控制台)面板
Sources(源代码)面板
Network(网络)面板
Performance(性能)面板
Memory(内存)面板
Application(应用)面板
Security(安全)面板
Audits(审计)面板
# 1.元素面板(Elements)
编辑样式 使用 Styles(样式)窗格修改与元素关联的 CSS 样式。
Styles (样式)窗格允许您以尽可能多的方式更改本地 CSS,包括编辑现有样式,添加新样式,添加样式规则。 如果你想要样式持久(他们页面重新加载而丢失),您需要将它们持久化到您的开发工作区。
# 检查应用到元素的样式
选择一个元素[Select an element] 来检查它的样式。Styles(样式)窗格将显示所有应用于所选元素的 CSS 规则,优先级从高到低展示:
在顶部是 element.style 。这些是使用 style 属性直接应用于元素的样式(例如, < p style="color:green" > )(愚人码头注:内联样式),或是你在 DevTools 该区域编辑应用的。 下面是与元素匹配的所有 CSS 规则。例如,在下面的屏幕截图中,所选元素接收 line-height:24px 的规则,定义在 tools.css 中。 下面是继承的样式,包括匹配所选元素的祖先元素所有可继承的样式规则。 例如,在下面的屏幕截图中,所选元素继承了来自 user agent stylesheet 中的 display:list-item 规则。 请查看下面图片上,与下面编号相对应的条目。
一般来说,对于前端就是编辑器或者浏览器
使用本地的编辑器,如 VSCode,好处是可以直接在源码中进行操作,也方便即时修改代码,不足之处是调试较为麻烦,并且需要做一些配置后才能进行调试(具体可以自己去配一下,这个用来刷算法题还是比较爽的);
使用谷歌浏览器,好处是拥有足够多的功能,可以基本上满足开发的需求,不足之处大概就是需要配置项目生成 sources map,并且在浏览器中修改的源码无法在项目中同步,即需要在项目里找到对应文件才能进行修改代码;
# 2.控制台面板(Console)
# Console API 参考
使用 Console API 将信息写入控制台,创建 JavaScript 配置文件和启动调试会话。
# console.assert(expression, object)
如果计算表达式返回 false 时,向控制台写入一个 error。
function greaterThan(a,b) { console.assert(a > b, {"message":"a is not greater than b","a":a,"b":b}); } greaterThan(5,6);
# console.clear()
清空控制台。
# console.count(label)
写入 count()在相同的行和相同的标签已被调用的次数。
function login(name) {
console.count(name + ' logged in');
}
2
3
# console.debug(object [, object, ...])
与 console.log()相同。
# console.dir(object)
打印指定对象的 JavaScript 表示形式。 如果正在记录的对象是 HTML 元素,那么打印为 DOM 表示的属性
# console.dirxml(object)
如果可能,打印对象的后代元素的 XML 表示,或 JavaScript 表示(如果没有)。 在 HTML 和 XML 元素上调用 console.dirxml()等效于调用 console.log()。
# console.error(object [, object, ...])
打印的消息类似于 console.log(),将消息样式化为错误,并包含调用该方法的堆栈跟踪。
console.error('error: name is undefined');
# console.group(object[, object, ...])
具有可选标题的新日志记录分组的开始。 在 console.group()之后和 console.groupEnd()之前发生的所有控制台输出可视为一个分组
function name(obj) {
console.group('name');
console.log('first: ', obj.first);
console.log('middle: ', obj.middle);
console.log('last: ', obj.last);
console.groupEnd();
}
name({"first":"Wile","middle":"E","last":"Coyote"});
2
3
4
5
6
7
8
9
# console.info(object [, object, ...])
打印一个消息,如 console.log(),但还会在输出消息的旁边显示一个图标(带有白色“i”的蓝色圆圈)。
# console.log(object [, object, ...])
在控制台中显示消息。将一个或多个对象传递给这个方法。每个对象被单独计算并将其连接成一个由空格分隔的字符串。
# console.time(label)
启动一个与标签关联的新计时器。当使用相同的标签调用 console.timeEnd()时,计时器将停止计时,并且在控制台中显示执行时间。计时器的值精确到亚毫秒。传递给 time()和 timeEnd()的字符串必须匹配,否则计时器将不会停止计时。
# console.timeEnd(label)
如果当前计时器正在进行,则停止当前计时器,并向控制台打印计时器标签,然后显示已用时间。
有关示例,请参见 console.time()。
# console.timeStamp([label])
在记录会话期间向 Timeline(时间轴)面板添加一个事件。
# console.trace(object)
在调用该方法的地方打印堆栈跟踪。
# console.warn(object [, object, ...])
打印一个消息,类似于 console.log(),但在输出的消息旁边还显示一个黄色警告图标。
# 3.源代码面板(sources)
# 如何设置断点
使用断点来暂停 JavaScript 代码,审查变量的值和在特定时刻所调用的堆栈。
一旦你设置了断点,你应该学习如何遍历你的代码,并审查你的变量和调用堆栈。
# 在代码特定行上设置断点
当您知道要审查的语句时,在特定代码行上设置断点很有用。例如,如果您的登录流程未按预期工作,并且您的代码中只有一个函数来处理登录,那么可以安全地假设该错误可能在该函数中。在这种情况下,在该函数的第一行添加断点是有意义的。
当你在一行代码上设置断点时,代码总是会在这一行代码上暂停,直到您删除断点,禁用它,或使其有条件触发。
要在特定代码行上设置断点,首先打开 Sources(源文件)面板,并在左侧的 File Navigator(文件导航器)窗格中选择该脚本。如果找不到 File Navigator(文件导航器),按下 Toggle file navigator(切换文件导航器)按钮()。
提示:如果你使用缩略的代码,点击 pretty print(代码美化)按钮()使其可读。
在源代码的左侧,您可以看到行号。这个区域称为 line number gutter(行号槽)。单击行号槽中的行号,就会在该行代码上添加一个断点。
# 使一个行号断点有条件
只有当您指定的条件为 true 时,才会触发条件断点。
右键单击尚未设置断点的行号,然后点击 Add conditional breakpoint(添加条件断点)来创建一个条件断点。如果你已经在一行代码上添加了断点,并且希望使断点有条件,右键单击该断点,并点击 Edit breakpoint(编辑断点)。
在文本字段中输入你的条件,并按 Enter 键。
条件断点是金黄色的。
# 删除或禁用一个行号断点
如果你想临时忽略一个断点,然后禁用它。右键单击 line number gutter(行号槽)中该断点,并选择 Disable breakpoint(禁用断点)。
如果你不再需要一个断点,然后删除它。右键单击 line number gutter(行号槽)中该断点,并选择 Remove breakpoint(删除断点)。
您还可以在 Sources(源文件)面板上的 Breakpoints(断点)窗格中管理所有脚本中的所有行号断点。
要从 Breakpoints(断点)窗格界面中删除断点,右键单击该断点,并选择 Remove breakpoint(删除断点)。
技巧
快捷键 以下操作为 mac 电脑的快捷键
快捷键操作展示 command+option+i 打开调试工具,默认打开上一次关闭的状态 command+option+j 打开调试工具,默认打开 console 面板 command+shift+c 打开 element 面板 command+shift+d 改变面板的位置 command+shift+m 切换设备模式 command+[ 和 command+]切换面板 2. Elements 面板
这个面板很重要,静态的样式都是在这里查看的,HTML+CSS 左上角的箭头,点击后将鼠标移到页面,可以去查看对应的元素,并在面板中可以查看到这个元素的 DOM 结构,右侧可以查看这个元素的样式(包括其样式的来源 =》 可以查看样式是怎么被覆盖的)。并且在右侧的样式里可以进行编辑,编辑之后会直接在页面上展示出来,这个很适合编写前端 UI 的时候去调整 padding、margin 这些。 这里还能查看“盒子大小”、“布局 Grid/FlexBox”、“绑定的属性”、“元素绑定的事件”等。 对该元素的状态进行 debug,eg. 这个元素是 hover 才能显示,为了方便调试,往往会勾选这里的:hover 来使得这个元素处于 hover 状态,方便查看样式
常用:⭐️⭐️⭐️⭐️⭐️
审查元素,查看 dom 结构
调整 css 样式
查看样式覆盖原因
通过 classname 去查找对应的文件
- Console 面板 console 完全指北 - 掘金 Chrome DevTools 的 console 面板 - 掘金
这里是一个合格的 JavaScript 编辑器,往往我喜欢在这里进行一些 js 语句的编写,来查看自己使用的 api 是否正确。
😍 小福利 😍:在浏览器里使用第三方依赖!搭配 chrome 插件 console-importer if (!('_' in window)) $i('lodash') else { const result = _.map([1, 2, 3, 4, 5], i => i + 1) console.log(result) } 复制代码
项目中使用 console.log(xxxx)便是在这里进行打印输出
在控制台中还可以直接获取挂载到了全局的变量:
过滤功能:
常用:⭐️⭐️⭐️⭐️
查看项目中 console.log 内容
编写 js 语句
查看挂载到全局的变量
- Sources 面板 这里可以对源码进行断点调试,important! 同样的,这里也可以运行 js 代码,可以把算法代码粘贴到这里进行运行,控制台中可以直接调用这个文件里的方法,比起 Console 面板好处是可以进行调试
简单来认识一下这个面板吧,具体的使用会在下一个 part 进行展开
Threads:标识出当前启动的线程,可以切换
Watch:对变量进行监听
BreakPoints:点击代码左边数字那里会打一个断点
Scope:当前断点所在的作用域,可以看到当前作用域的所有变量的值
Local 本地作用域:代码当前 {} 内存在的变量,this 就可以在这里找到。 Closure 闭包作用域:代码当前所处闭包里的变量。注意名称后用括号注明了这是哪个闭包里的内容,因为闭包可以嵌套,所以可能出现多个 Closure 作用域。 Script 代码标签作用域:当前 标签里存在的变量,这个用的不多。 Global 全局作用域:这个就不用解释了吧。
Call Stack:调用栈,进入断点后这里会显示函数的调用次序(同步、异步),点击对应的可以跳转到对应的代码里
Dom Breakpoints: dom 变更的时候进入断点
Global Listener:显示所有绑定到 window 的事件监听器,点击可以跳转到对应的代码
Event Listener Breakpoints:列举了所有事件,触发后自动进入断点
断点:(从左到右)
点击运行到下一个断点,如果没有设置断点会直接运行完代码
点击运行代码到断点的下一行
点击跳进断点函数里进行调试
跳出当前函数调用
当前断点的下一步
在 page 面板修改是不会改变本地文件的,而这里的【overrides】可以选择保存到本地哪个文件夹里,选择保存到覆盖文件即可(Save for Overrides)
常用:⭐️⭐️⭐️⭐️⭐️ 用于调试代码
查看变量的执行情况
查看函数调用情况
判断函数是否执行
- Network 面板 http 协议报头详解 - 蚊子博客 - 博客园 Referrer Policy 介绍 | JerryQu 的小站 关于这个面板,对于前端来说,最重要的事情就是用来查看网络请求情况:
左上角的小红点,是一个开关:是否捕获网络请求
红色状态下,可以正常捕获网络请求;灰色状态,则停止捕获网络请求。一般用于分析网络,不想被新请求的网络干扰时,会使用这个功能
右侧是清除面板的网络请求情况
Preserve log :保留请求日志,跳转页面的时候勾选上,可以看到跳转前的请求(不勾选默认就是跳转到新页面就看不到之前的请求了)
Disable cache:忽略缓存,一般 get 请求会做一些缓存,主要是避免重复加载资源时的浪费
再往右,可以选择网速情况,有 4g 3g 等等情况,支持自定义,一般在这里选择无网状态,模拟用户断网的情况,或选择低网速模拟用户弱网状态
再往右,支持上传下载网络请求情况文件
往下有个输入框 Filter,可以对网络请求进行筛选,一般用于筛选对应的网络请求(输入 api 地址)
对资源进行分类:对于网络请求来说,一般分为【静态资源】&【动态资源】,其中动态资源也就是 api 接口请求,归属于“Fetch/XHR”,其他的就属于静态资源了,比如 js、css、字体、图片、视频等,都有对应的分类
网络请求:
(1)Name: 表示加载的文件名。 (2)Method: 表示请求的方式。 (3)Status: 表示状态码(200 为请求成功,304 表示从缓存读取)。 (4)Type: 表示文件的 MIME Type 的类型。 (5)Initiator: 表示发出这个文件请求的发出者。 (6)Size: 表示文件大小。 (7)Time: 表示每个请求的总时长。 (8)Timeline: 以图表的形式显示元素的请求和加载情况。
查看 watchfall:Chrome 控制台 Network Timing 面板 - 掘金
❗️ 查看网络详情:点开对应的网络,会有具体的情况
这里可以查看到网络请求的具体情况,几个比较重要的: header:查看请求的 url、method、status 等等,包括跨域也会在这里进行体现,以及一些请求头携带的特殊参数,例如 logId payload:请求的 request 参数 response:请求的 response 参数 preview:对请求回来的参数进行格式化,方便查看 cookies:改请求对 cookie 的操作 其他查看较少,一般用于优化网络加载情况时会使用的
常用:⭐️⭐️⭐️⭐️⭐️
设置网速
查看接口请求情况:状态码、返回参数等
查看请求时间、数量
网络优化
- Performance 面板 chrome devtools 使用详解--Performance - 掘金 用于分析页面运行性能,做优化的时候使用
常用:⭐️⭐️
页面整体的网络加载情况
监控页面整体性能
- Application 面板 Chrome 开发工具之 Application - 走看看 这里最主要的是查看 LocalStorage、SessionStorag、Cookies
常用:⭐️⭐️⭐️
查看缓存情况
清除缓存
- 实操 对于一个项目,我们可以通过调试的方式去了解这个项目的逻辑
通过元素审查,拿到 classname,到项目中搜索,一般可以找到对应的代码文件,方便我们将代码定位到一个文件里
此时知道代码的位置了,可以粗略的查看该文件是什么组件、有什么功能、大致的函数调用关系,此时就可以通过打断点的形式去开启 debug
debug 的入手点:
有 dom 的变化,直接对 dom 打断点。eg、对输入框所在的 dom 打一个断点,当你在输入框中输入内容的时候,代码会停住在这个操作执行的第一个函数
初始化或者特定时机执行的函数,例如初始化执行的函数,可以直接对生命周期函数打断点,以此以此执行代码找到对应的函数
行为对应的函数,这个需要对代码函数执行有一定的了解,eg、点击发送按钮,在代码中看到了这个按钮绑定的点击事件,将断点打在这个函数里
断点打好了,通过调试器对代码进行调试:
在未知的情况下,使用【第二个】,执行下一行代码
想要查看某一行的变量,在变量那一行加一个断点,使用【第一个】,直接跳到下一个断点的位置
在执行的时候,遇到有调用其他函数,使用【第三个】,进入该函数里
使用【第四个】从当前执行的函数中跳出来,回到调用该函数的方法里(一般和第三个配合使用)
使用【第五个】直接不调用这个方法
在调试过程中,主要查看:
变量的情况,在【watch】中加入想要看的变量 或者 在【scope】中直接查看
函数调用情况,在【call stack】中查看,并且可以看到同步&异步栈中的入栈函数