命令菜单
先打开控制台: 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标签里可以看到Grid
flex
勾选中某个元素后,可以用现况展示元素的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');
// vs
console.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. 1
const aa = 1;
console.assert(aa === 1, '对劲');
console.assert(aa === 2, '不对劲');
console.assert(aa === 3, {msg: '不对劲' });
// e.g. 2
const 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 () {
debugger
a();
};
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