命令菜单
先打开控制台: ctrl + alt + j
Windows: ctrl + shift + p
Mac: command + shift + p
截屏
- capture area
screenshot - capture full size
screenshot - capture node
screenshot - capure
screenshot
主题
switch to dark themeseitch to light theme
dock
devtools的位置dock to left/right/bottomundock 独立窗口
Element
command + F 查找
- tagName
#id div#test - tagName
.classname div.test
全部展开元素
alt 按住 + 点击元素,展开内部所有元素
Xpath
Xpath 是使用路径表达式来选取xml文档中的节点或者节点集,节点沿着路径path或者步step来选取的。
| 表达式 | 描述 |
|---|---|
| nodename | 选取此节点的所有子节点。 |
| / | 从根节点选取(取子节点)。 |
| // | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置(取子孙节点)。 |
| . | 选取当前节点。 |
| .. | 选取当前节点的父节点。 |
| @ | 选取属性。 |
//article[@id="content"] 匹配全局id属性为 ‘content’ 的 article元素//div/ne-p选取所有div元素下的ne-p元素//div/ne-p/ne-card 选取所有div元素下的ne-p元素的ne-card元素。那如果我想直接选取到ne-card元素可以用 // **//div//ne-card**//*[@id='content']/div[1]/div/div/div[1]/div[2]/ne-p[1]/ne-card id为content的任意元素的第1个子div的子div的第一个子div的第二个div下的第1个ne-p元素的ne-card元素
如何获取Xpath,在元素上右键 -> copy -> copy Xpath。copy还可以获取其他格式,比如js获取方式。
$x 函数
接受xpath为参数,打印出DOM元素$x('//*[@id="content"]/div[1]/div/div/div[1]/div[2]/ne-p[1]/ne-card') 在控制台里打印所选元素。$x('//img')$x('//*[@id="content"]')
inspect函数
在console定位DOM元素在Element面板的位置
inspect(document.querySelector('#content')) inspect($x('//*[@id="content"]')[0]) 同上
复制样式
在想要复制的节点上右键 -> copy -> copy styles。
hover常驻
只取消某样式中一个的样式
.cls
有多个样式,我只想取消某一个样式,不想所有采用这个样式的元素都被改变。可以从 .cls中取消某个class的选中状态,只针对当前的元素生效。
layout
Element面板的layout标签里可以看到Gridflex

勾选中某个元素后,可以用现况展示元素的flex\grid布局情况
EventListeners
查看元素下绑定的事件
- remove事件
有时候在一些使用框架的页面中,在目标元素上remove 事件监听函数,仍旧可以触发,因为像React框架,并不是将事件绑定在目标元素的真实dom上的,而是在document监听所有的事件,当事件冒泡到document的时候,React将实践内容封装并交由真正的处理函数处理。所有需要remove document上的事件。

- show function definition
在console面板中,对象方法可以右键,展示方法的定义处位置
DOM breakpoint
这里有三个选项:
- subtree modifications 此节点下的节点改变时断点
- attribute modifications 此节点属性变化时断点
- node removal 次节点被删除时断点
添加节点:const t = document.createElement('div'); $0.appendChild(t);, 触发断点
属性变化: 首先我们选中这个节点,然后 $0.setAttribute('id', 1), 就可以触发断点
Console
command + alt + j
$_
返回上一次的输出结果
$0
返回上一个选择的DOM节点
$1 上上个
$2 上上上个
以此类推
$() / $$()
$ = document.querySelector$$ = document.querySelectorAll
console方法
- console.log
- console.error
- console.warn
- console.count
被调用次数计数
for (let i of Array(100).fill(1)) {console.count('共计')};
console.table
console.table([{id: 1,name: 'lucy'},{id: 2,name: 'lily'},])// 可以点击排序
console.clear
清空控制台 / command + k
console.group
console.group('test');console.log(1);console.log(2);console.groupEnd('test')
console.time
常用在一些计时场景下
console.time('time')for (let i of Array(1000).fill(1)) { console.log(1) }console.timeEnd('time');// vsconsole.time('time')const arr = Array(1000).fill(1);for (let i = 0; i < arr.length; i++) { console.log(1) }console.timeEnd('time');
- console.assert
如果断言为false,则将一个错误信息写入控制台。断言为true,则没有任何反应
// e.g. 1const aa = 1;console.assert(aa === 1, '对劲');console.assert(aa === 2, '不对劲');console.assert(aa === 3, {msg: '不对劲' });// e.g. 2const errorMsg = '此数不是偶数';for (let number = 2; number <= 5; number += 1) {console.log('此数为' + number);console.assert(number % 2 === 0, {number, errorMsg});};
- console.trace
向控制台输出堆栈跟踪。显示到调用console.trace() 的点的调用路径。
function foo() {function bar() {console.trace();}bar();}foo();
观察变化👁
// 点击console面板的眼睛,输入b,可以观察到b的变化let b = 0;setTimeout(() => { b = 99 }, 3000);
Native Import
在控制台直接加载工具库。
const lodash = await import('https://cdn.skypack.dev/lodash');lodash.get({a:1}, 'a')
Sources
JS调试
function a () {console.log(1);console.log(2);console.log(3);}function foo () {debuggera();};foo();
进入函数,离开函数。
command + shift + p -> disable/enable code folding 打开源代码代码折叠
条件断点
假如有这么一段代码
const aa = Array(10).fill(1);function test () {debugger;aa.forEach((e, index) => {console.log(index)});};test();

则,将会在index == 5 时进入这个断点,而其他时候不会。
适用于一些重复执行的逻辑中
Global Listener Breakpoints
选择 click, 那么在页面点击登录时,会触发debugger。

点击F8,我们会在callstack 里看到,有些框架代码的断点:
框架里的click断点我们不关心,那么可以
最后可以看到有个全局的click事件,可能就是我们需要找的事件处理函数

Network
throtting
network conditions
底部栏
分别是 全部请求数量、请求传输体积、页面使用的资源体积、全部资源请求完毕时间、初始的 HTML 文档完全加载并解析完成时间、页面完全加载完成时间(包括了js和css加载解析完成)。
重新发送/阻止请求/阻止该域
复制请求
复制请求,并在控制台修改参数,重新发起

fetch("http://x.yupoo-dev.cn/api/v2/login", {"headers": {"accept": "application/json, text/javascript","accept-language": "zh-CN","content-type": "application/json"},"referrer": "http://x.yupoo-dev.cn/login?url=%2Fhome","referrerPolicy": "strict-origin-when-cross-origin","body": "{\"sig\":\"05a1C7nT4bR5hcbZlAujcdyfrs1t9uUVkGfX5qKSg4vVmZKeAaQxLeBuRaqiXWwMMU622KgCR95FFl02HnB5i7wU32sgBp1QY55xAXCxE4wqdiGp4-RSlo2wwzH2kqN58cqr31_UIH4_t1IYsp84icbMV6gI60n7v9CghMVUr4tRRwMs581Gdr6MUR43pdrIBU6LM5Cx81Ogd02eaF1MNBxTHZrMxYDrdT3P23TE7sef6J5qhY_MrcYaNOV0HVaB0v01Ar3YahFiLVfGqfBS59zpZ1VtpQz4EvZlTYYXRlwrnZPOwRifLpqc28ILke2rd1zoxpJGHunCArV7eYCr_mIE_kLOroWTZ6DkRgI3S-7M_q7M-xhPDktxNVzLoQ-gazQSm0XOogqBFVZ40diMjZ-j0ZFS1mz4z4HP5D9PkHdQTiPKYMZNQqb4mK0t8MSLFT0DGhRccNKcbpRrCTX-0Q-Uuz8ZT_89WxoY7Pr-WaOUM\",\"csessionid\":\"0152JIZgtMjy7iQLwB8JakWRq_6Az4PhELGaX2L342ip_KdofNKP2aNDU3D3ltiP2YYLrfwlX-gBHQuACMhAIq39ILksAsi_jOiYiArUQCcwdB868MvOl8tcUwL1pP4Cneg56Fh18oTEVFxp5z_cC0foaH4dW-btbRmTFMof4RIPR33XfUTjjfgU_pDeYFtTBOnALcbseNIzyI6tVyQ-jUIA\",\"nc_token\":\"FFFF00000000017682F5:1650205746924:0.7799567398665481\",\"nc_scene\":\"nc_login\",\"username\":\"xixi99\",\"password\":\"123123\"}","method": "POST","mode": "cors","credentials": "include"});
导出导入HAR
这东西是干嘛用的呢? 最常用的场景应该是复现网络情况。比如用户在使用页面时,网络异常,但是我们本地网络状况无法复现。
这时候,让用户打开network面板,重新请求,然后点击向下的箭头,这时候会生成一个har文件。将文件发给我们,我们在本地点击向上的箭头,导入,就可以看到他的网络请求状态了。
比如我们通过导入har,发现他有个接口报错了
Application
localStorage
sessionStorage
cookies
