Gahing's blog Gahing's blog
首页
知识体系
  • 前端基础
  • 应用框架
  • 工程能力
  • 应用基础
  • 专业领域
  • 业务场景
  • 前端晋升 (opens new window)
  • Git
  • 网络基础
  • 算法
  • 数据结构
  • 编程范式
  • 编解码
  • Linux
  • AIGC
  • 其他领域

    • 客户端
    • 服务端
    • 产品设计
软素质
  • 面试经验
  • 人生总结
  • 个人简历
  • 知识卡片
  • 灵感记录
  • 实用技巧
  • 知识科普
  • 友情链接
  • 美食推荐 (opens new window)
  • 收藏夹

    • 优质前端信息源 (opens new window)
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Gahing / francecil

To be best
首页
知识体系
  • 前端基础
  • 应用框架
  • 工程能力
  • 应用基础
  • 专业领域
  • 业务场景
  • 前端晋升 (opens new window)
  • Git
  • 网络基础
  • 算法
  • 数据结构
  • 编程范式
  • 编解码
  • Linux
  • AIGC
  • 其他领域

    • 客户端
    • 服务端
    • 产品设计
软素质
  • 面试经验
  • 人生总结
  • 个人简历
  • 知识卡片
  • 灵感记录
  • 实用技巧
  • 知识科普
  • 友情链接
  • 美食推荐 (opens new window)
  • 收藏夹

    • 优质前端信息源 (opens new window)
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 前端基础

    • 编程语言

    • 开发工具

    • 前端调试

      • 如何防止页面被 F12 调试
      • hybrid 远程调试的前世今生
      • 通读「你不知道的 Chrome 调试技巧」
        • 前言
        • 通用篇
          • 1. copy(value)
          • 2. 快捷键
          • 3. 使用 Command
          • (1) Debugger - disable JavaScript
          • (2) Screentshot 指令截图
          • 4. 代码片段 Snippets 的使用
        • console 篇
          • 1. console 中的 $
          • $0~$4
          • $ 和 $$
          • $_
          • $i
          • 2. Ninja console.log
          • Conditional breakpoints 条件断点
          • The ninja console.log
          • 3. 方法代理
          • debug 调试方法
          • monitor 监听方法调用
          • monitorEvents(object[, events]) 监听事件调用
          • 4. Live expression 功能
          • (1) dom 节点个数统计
          • (2) 计算数学表达式
          • (3) 展示当前点击位置坐标
          • 其他
        • Network 篇
          • 1. 关闭 overview 扩大请求面板空间
          • 2. 禁用请求
          • 3. XHR/fetch 断点
        • Elements 面板篇
          • 1. 通过 h 去隐藏元素
          • 2. 颜色选择器的 Contrast ratio(对比度)
        • Drawer 篇
          • 1. Changes
        • Workspace 篇
        • 总结
    • 浏览器原理

    • 浏览器生态

  • 应用框架

  • 工程能力

  • 应用基础

  • 专业领域

  • 业务场景

  • 大前端
  • 前端基础
  • 前端调试
gahing
2020-08-31
目录

通读「你不知道的 Chrome 调试技巧」

# 前言

本文是对掘金小册 「你不知道的 Chrome 调试技巧」 (opens new window) 的阅读笔记与思考。

该小册记录了一些可能少为人知却挺有用的技巧。在此基础上,我筛选出一些此前不知道的技巧,偏个人向,完整的可以阅读原小册。

当然,如果你完整的阅读过 chrome-devtools 系列文章 (opens new window) ,这些技巧应该都知道。

除了技巧罗列,本文会加入一些思考,比如这个技巧用来解决什么问题,其他浏览器如何模拟实现等等。

# 通用篇

# 1. copy(value)

调用全局的 copy 方法,将 value 值复制到剪切板

在此之前,我们我们想复制一个对象的值,我们会怎么做?笨点的做法,可能会将其输出,然后层层展开,复制完再去掉一些无用or重复文本(懂的都懂);或者再聪明一点,用 JSON.stringify(val,null,2) 带缩进输出后再复制

然而,现在仅需要用 copy 方法即可快速复制了。

借用原文的图

经过几组实验,发现 copy 值时内部调用的是 JSON.stringify(val,null,2) ,且在存在循环引用等调用 stringify 会报错的情况, 执行 copy 后剪切板复制到的值是 [object Object]

let a = {say:()=>{},name:'gahing'}
copy(a) // {name:'gahing'}
a.toJSON = ()=>1
copy(a) // 1
a.c=a
copy(a) // [object Object]
1
2
3
4
5
6

所以,对于其他浏览器,也可以写一个全局的 copy 方法,以供使用:

window.copy = (val) => {
    const getData = (val) => {
        if (val instanceof Element) {
            return val.innerHTML
        }
        try {
            return JSON.stringify(val, null, 2)
        } catch (error) {
            return '[object Object]'
        }
    }
    const writePasterVersion = (data) => {
        // 利用 textarea 可以保留换行等格式
        const textarea = document.createElement('textarea')
        document.body.appendChild(textarea)
        textarea.setAttribute("readonly", true)
        textarea.value = data
        textarea.select()
        if (document.execCommand('copy')) {
            document.execCommand('copy')
        }
        document.body.removeChild(textarea)
    }
    const data = getData(val)
    writePasterVersion(data)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

注意这里还加入了复制 dom 元素内容的处理,原 copy 方法也是支持这个的。不过复制 dom 这个功能大部分浏览器也都支持就是了。

# 2. 快捷键

文中以及其他的一些文章都提到了快捷键技巧。

这个其实不用太去记,忘了就打开 Shortcuts 面板看看(打开控制台=>按 F1=>切到 Shortcuts 面板 ),用多了就熟了。

或者看 google dev 原文-> 键盘快捷键参考 (opens new window)

小册中提到 Cmd + 数字可以用来切控制台的面板,不过需要先去设置那边开启 DevTools>>Settings >>Preferences>>Appearance 打开这个选项:

这里额外发现,原先的 Cmd + 数字 快捷键更实用,可以用来切 tab ,很适合上班摸鱼(划掉)。

# 3. 使用 Command

用过 VS Code 的就知道, 我们可以通过 Cmd + Shift + P 吊起 Command 菜单,其实浏览器也有相同的操作(需要先打开开发者工具)

包括的功能有:

上图引自小册

大部分指令就是通用设置和操作,其实可以在 Settings 里找到相应的设置和快捷键,所以大部分情况也没什么用,这里说下两个我个人觉得无可替代的 Command 功能

# (1) Debugger - disable JavaScript

相应的也可以在 Settings - Preferences 找到相应的配置,那为啥说无可替代呢?

我们应该经常遇到这样的需求:鼠标移动到某个区域时出现一个浮窗,移开时浮窗消失。浮窗的显隐是利用 js 的 mouse 事件来控制的。此时我们想调试浮窗的 dom 结构怎么办?

之前尝试过的操作有以下几种:

  1. 右键-检查定位到 Elements 面板的 dom ,通过 Tab 和 方向键等调试样式,操作受限,且经常一不小心就消失浮窗导致白调试了。
  2. 先打开 Settings - Preferences 面板,鼠标指向相应位置出现浮框的时候,快速切到 Preferences 面板设置 disable JavaScript ,不过这需要一个比较好的角度和手速,成功率不高。

今天发现可以通过提前切出 Command 面板,焦点处于输入框中,此时鼠标移动到相应区域显示浮窗。另一方面, Command 面板输入 Disable JavaScript 并回车禁用 js ,接下来就可以为所欲为了~

20200915 更新: 这个方案处理不了需要点击的情况(比如点击选择框后展现下拉列表)。后经同事指点,提供了其他方案:

  1. settimeout debugger
  2. 父元素断点调试:Elements 面板 -> 父元素右键 Break on -> subtree modifications

# (2) Screentshot 指令截图

输入 screentshot ,可以看到有以下指令:

  • Capture area screentshot: 选择一个矩形区域并截图
  • Capture full size screentshot: 整个网页截图
  • Capture node screentshot: 单独截图某个节点区域,需要先去 Elements 面板选中节点再执行指令。
  • Capture screentshot: 截图当前网页可视区域

这四个指令,基本能够满足我们对网页静态截图的种种需求,一些 Chrome 拓展可以选择卸载了~

# 4. 代码片段 Snippets 的使用

我们经常会在控制台写一些临时用的测试代码。但是可能隔很久之后又要用到它,再重写一遍有点浪费时间。

Chrome 给我们提供了一个编写代码片段,之后随时随地(任意页面)都可以执行这段代码的功能。

我们可以在 Sources 面板的 Snippets 栏中新建 snippet ,写完代码后通过右击菜单 run 或者快捷键 Cmd + Enter 来运行它

上图引自小册

甚至可以通过 Cmd + P 切出 Open file 功能后输入 ! ,之后选择 snippet 并回车来运行代码片段

上图引自小册

目前能想到的几个使用场景就是:

  1. 编写单测 or 基于 fetch 的接口测试代码
  2. 编写通用工具方法
  3. 引入某些 npm 包(比如 moment/loadsh 等)的 umd cdn script 地址到页面,并测试该 npm 包的功能
  4. 做断点测试(下文会提到)

不过对我来说,这个功能有点鸡肋。一方面很少用到,另一方面就算不用它我们也有各种替代品,比如输入几个关键字 console 就能跳出历史输入记录。

且实测 Snippets 数据不能进行 Chrome 间数据同步, 如果能同步的话更有用些,可以组装上自己的工具库了。

# console 篇

大部分技巧都可以在 Chrome DevTools Console 原文 (opens new window) 中找到

# 1. console 中的 $

# $0~$4

$0 表示对当前选中节点的引用, $1 表示对上次选中节点的引入,以此类推直至 $4

所以我们可以很简单的进行 dom 节点移动

<div class="list">
  <div class="item"></div>
  <div class="item"></div> <!--先选中这个节点 $1 -->
</div>
<div class="content"></div> <!--再选中这个节点 $0 -->
1
2
3
4
5

应用

$1.appendChild($0) //即可实现 dom 节点移动
1

# $ 和 $$

$ 相当于 document.querySelector 的别名

$$ 类似于 document.querySelectorAll ,但是返回的是节点数组,而不是 NodeList 类数组对象

$ 和 $$ 还支持第二个参数 startNode 即查询起点 document 改为 startNode

$("div",$("div"))
1

其他浏览器的简单 mock (没做异常处理和特殊判断)

window.$ = (selector, startNode) => (startNode || document).querySelector(selector)

window.$$ = (selector, startNode) => Array.from((startNode || document).querySelectorAll(selector))
1
2
3

# $_

上次执行结果的引用

上图引自小册

其他浏览器倒是不好 mock 这个功能。不过这个功能也挺鸡肋的就是

# $i

在此之前,控制台调试 npm 包是一个痛点,我们可能会:

  • 新建项目->安装 npm 包->打包输入到 html 页面->devtools 测试,或者
  • 找到 umd 包地址->script 引入->devtools 测试

现在,仅需要在控制台执行 $i(npm_package_name) 即可引入该 npm 包了

严格来说,这个是 Chrome 拓展 Console Importer (opens new window) 的功能,并不是 devtools 自带的。也就意味着你需要先安装这个拓展,它会将 $i 方法插入到全局。

示例

上图引自小册

不过使用上有个体验稍微欠缺的点:引入后没有告知 window 上挂载的是哪个变量

因为有些包挂载的变量不一定是 npm 包名,比如 loadsh 的 _ 。可能可以通过比对 window 前后挂载变量差异来实现

同时希望能支持上内网 npm 包引入,可能可以通过指定仓库源 or umd 地址来实现

该拓展的项目地址为 console-importer (opens new window),正好最近在研究浏览器插件,以上两个问题有空可以去提个 pr

TODO: 后续实现会再写个文章

# 2. Ninja console.log

# Conditional breakpoints 条件断点

这个对我来说还是挺实用的,仅当满足某个表达式才进入断点,很适合在循环代码中按条件进行断点调试

操作:

  1. 右击行号,选择 Add conditional breakpoint...(添加条件断点)
  2. 填入表达式,返回结果为 falsy (opens new window) 时不会暂停

上图引自小册

如果只想体验这个功能的话,我们还需要新建一个 html 文档并引入 script 才能玩么?

并不用,还记得上文提到的代码片段 Snippets ,它同样支持调试,所以新建一个代码片段并开始体验吧

// 代码片段
let res = 0
Array.from(Array(15))
.map(Math.random)
.forEach((v,i)=>{
    res += v*i
})
console.log(res)

// 断点表达式
v>0.8
1
2
3
4
5
6
7
8
9
10
11

# The ninja console.log

上面说到,表达式结果为 falsy 时不会暂停,这也就意味着我们可以使用 console.time/log/group 等代码作为表达式,它不会影响断点流程,但是却可以正常输出。

以后再也不需要在源代码里面输入 console 代码了

上图引自小册

另外发现了一个 logpoint 操作,大概就是表达式里直接写参数,之后通过 console.log 帮你输出

所以上面的 console 相关操作通过 logpoint 也是可以的,且更符合语义

# 3. 方法代理

在方法被调用时,我们可以进行一些操作,包括触发调试,输出入参等等

编写方法

function add(x,y){
  return x+y
}
1
2
3

# debug 调试方法

如何调试这个方法呢?

执行

debug(add)
1

当调用方法时就会进入调试面板

add(1,2)
1

可以通过 undebug 取消调用调试

因此调试方法,我们仅需要知道方法名就行了,不需要知道在代码中哪个位置再去设断点。

该方法的实现:

window.debug = function (fnName, ctx = window) {
    let originFn = ctx[fnName]
    ctx[fnName] = function (...res) {
        debugger
        originFn.apply(ctx, res)
    }
}
1
2
3
4
5
6
7

测试用例

class Animal {
  constructor(name){
    this.name = name
  }
  eat(food){

  }
}
let cat = new Animal("cat")
// debug(cat.eat)
debug('eat', cat)
cat.eat("fish")
1
2
3
4
5
6
7
8
9
10
11
12

不同于原本的 debug 方法,我们需要显式的传入上下文和方法名。同时进入 debugger 时还得操作几下才能进入 eat 方法

如果有更好的实现,欢迎分享~

后续有机会的看下 Command API 是怎么处理的,能否只使用 js 能力就能够实现

# monitor 监听方法调用

我们想知道我们编写的代码是否被调用,以及入参是什么,以往我们可能会写 console.log代码,但有了 monitor 我们将不再需要了

monitor(add)
add(1,2)
// output: 
// function add called with arguments: 1, 2
// 3
1
2
3
4
5

该方法的实现:

window.monitor = function (fnName, ctx = window) {
    let originFn = ctx[fnName]
    ctx[fnName] = function (...res) {
        console.log(`function add called with arguments: ${res.join(',')}`)
        return originFn.apply(ctx, res)
    }
}
1
2
3
4
5
6
7

缺点同上,有更好的做法欢迎分享~

# monitorEvents(object[, events]) 监听事件调用

monitorEvents(window, "resize");
1

执行上述代码,当窗口大小变化时会输出以下内容

resize Event {isTrusted: true, type: "resize", target: Window, currentTarget: Window, eventPhase: 2, …}

resize Event {isTrusted: true, type: "resize", target: Window, currentTarget: Window, eventPhase: 2, …}

resize Event {isTrusted: true, type: "resize", target: Window, currentTarget: Window, eventPhase: 2, …}

resize Event {isTrusted: true, type: "resize", target: Window, currentTarget: Window, eventPhase: 2, …}
1
2
3
4
5
6
7

此外 event 还支持数组和映射,更多可查看 https://developers.google.com/web/tools/chrome-devtools/console/utilities#monitorevents

mock 的话,赶紧就直接用 addEventListener 即可

# 4. Live expression 功能

在 Console 面板的 "眼睛" 符号处开启。

类似 Vue 中的 computed ,书写一个表达式,当表达式中的成员变量变化时,结果会实时更新展示。

示例:

上图引自小册

目前想到的使用场景有:

# (1) dom 节点个数统计

document.querySelectorAll("*").length
1

# (2) 计算数学表达式

Math.pow(2,n) + 1
1

# (3) 展示当前点击位置坐标

// 控制台先输入
document.addEventListener("click",({clientX,clientY})=>myPosition=({clientX,clientY}))

// Live expression 为
myPosition // 效果类似上图示例,这里不再展示
1
2
3
4
5

# 其他

  • console 面板中可以直接用 await ,无需包裹 async iife
  • 测试回调参数时,直接在回调中使用 console.log 是更佳的做法: getLocation(console.log) ,不要 getLocation((v)=>console.log(v))

# Network 篇

# 1. 关闭 overview 扩大请求面板空间

overview 是一些时间轴信息,大部分情况下我们并不需要,还占面板空间

可以在设置中关掉它(上图 show overview 处)

# 2. 禁用请求

想看看当某些脚本、样式文件缺少或者其他资源加载失败时,网页的样子吗?在 Network 面板对某条请求右击选择 Block Request URL。一个新的 禁用请求 面板会被呼出,在这里可以管理被禁用的请求。

(以上引自官方原文)

在 禁用请求 面板中设置 url 规则会更方便,还支持正则

# 3. XHR/fetch 断点

在 source 面板右侧 XHR/fetch Breakpoints 新建断点

示例如下:

上图引自小册

比如对表单提交请求做断点,查看提交数据是否正常(当然也可以在 network 面板中看数据)

目前没发现这个功能的必要使用场景

# Elements 面板篇

# 1. 通过 h 去隐藏元素

选中元素,按下 h ,此时会给元素加上一个 style 样式,用来隐藏元素

visibility: hidden !important;
1

再按一次则显示元素

# 2. 颜色选择器的 Contrast ratio(对比度)

打开文本的调色选择器,可以看到 Contrast ratio 属性,其表示文字颜色和背景色的对比度

有三种情况:

  1. 🚫:表示对比度太低
  2. ✅:表示遵从 AA 声明,至少为 4.5
  3. ✅✅:表示遵从 AAA 声明,至少为 7

上图引自小册

展开 Contrast ratio 后,颜色面板还会出现 2 条线,用来指导开发者选择满足相应标准的对比度

# Drawer 篇

通过 More Tools 打开

因为更少用到,所以入口会更深。这里说下一个新发现的比较实用的功能。

# 1. Changes

我们经常在控制台上,对线上页面进行样式调试。

当调试结束时,怎么确定我改了哪些样式?人脑记?

这时候 Changes 功能就可以满足我们的需求

它会记录文件变化的情况,就像 git 一样,还支持撤回某些修改

上图引自小册

不过需要注意的是,对于压缩过的 css 来说,样式只有一行,这个 Changes 功能没啥用

# Workspace 篇

大部分情况下,我们是通过框架和打包工具进行开发的,这个功能不是很好用(也可能是我姿势不对),这里不再赘述。

对于纯 js/css 的小项目来说这个功能可能比较有用,感兴趣的可看小册原文 (opens new window)

总的来说一句话,改动是相互同步的

# 总结

Chrome Devtools 提供了很多强大的功能,解决了许多痛点,不过部分功能也很鸡肋

Devtools 的功能在不断更新,仅仅阅读他人的文章是当不了最潮的 debug boy 的,还是得多看看官方文档 😏

编辑 (opens new window)
#Devtools#通读
上次更新: 2024/09/01, 23:56:56
hybrid 远程调试的前世今生
Devtools Console 面板输入了 1+1 ,浏览器内部发生了什么?

← hybrid 远程调试的前世今生 Devtools Console 面板输入了 1+1 ,浏览器内部发生了什么?→

最近更新
01
浅谈代码质量与量化指标
08-27
02
快速理解 JS 装饰器
08-26
03
Vue 项目中的 data-v-xxx 是怎么生成的
09-19
更多文章>
Theme by Vdoing | Copyright © 2016-2024 Gahing | 闽ICP备19024221号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式