模板代码解释 
这个插件是一个学习的切入点。它只包含一个开关逻辑,就是你点击它在工具栏的图标,它图标下方就有个蓝底白字的“ON”,再点一次就取消。

下载、加载相关
如果你还没有下载代码模板,详见:课前准备:下载并加载模板
元数据文件 
看一个插件的代码,首先看它的“元数据文件”,也就是manifest.json。粗看起来很多,但名字(name)、描述(description)、版本(version)、图标(icons)跟代码本身不强相关,可以暂时忽略、不动。
json
{
  "name": "CopyQ",
  "description": "网页复制不了?插件帮你",
  "action": {
    "default_title": "点击开启复制模式"
  },
  "manifest_version": 3,
  "version": "0.0.1",
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "background": {
    "service_worker": "service_worker.js"
  },
  "icons": {
    "16": "icons/[email protected]",
    "32": "icons/[email protected]",
    "48": "icons/[email protected]",
    "128": "icons/[email protected]"
  }
}也就是说,先集中看:
json
{
  "action": {
    "default_title": "点击开启复制模式"
  },
  "manifest_version": 3,
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "background": {
    "service_worker": "service_worker.js"
  },
}action是用来控制工具栏图标行为的,其下的default_title表示悬停在图标时显示的标题;manifest_version也可以先不管,它是这份元数据文件(manifest)的版本,不同版本的文件格式要求、插件权限有所不同,但 Chrome 跟 Edge 只认 3 这个版本。之前一直是版本 2 的 Firefox 也在迁移了;permissions是插件要申请的权限,不同权限代表着浏览器提供的不同应用接口(API)。activeTab能临时访问当前活跃的标签页[1],配合执行脚本的scripting权限,插件可以在这些网站上插入脚本;background是后台脚本。可以用来沟通各个界面、处理跨域网络请求等。“worker”是在程序中执行特定任务的线程,service_worker在Edge被翻译成「服务工作进程」,这里的后台脚本是service_worker.js。
后台脚本 
如果你读过谷歌的中文文档,它有时有叫“背景脚本”,这是机翻的问题。
言归正传,看看service_worker.js的代码:
js
const on = 'ON';
chrome.action.onClicked.addListener(async (tab) => {
    // 获取当前标签页徽章(Badge)的文本
    let text = await chrome.action.getBadgeText({ tabId: tab.id });
    // 打开(ON)的时候就关掉(空字符),关闭的时候就打开。
    if (text === on) {
        text = ''
    } else {
        text = on;
    }
    // 设置当前标签页徽章(Badge)的文本
    chrome.action.setBadgeText({ tabId: tab.id, text: text });
});整体就是把工具栏的图标做成一个开关,开的时候徽章为“ON”,关的时候没有徽章(徽章没有字),
chrome.action就是控制工具栏行为的api;onClicked.addListener为鼠标单击这一事件添加监听函数,输入为标签页对象(浏览器控制输入);- 徽章(Badge)文本控制的API,可参考文档(注意机翻的“徽章”跟“标记”都有可能是 Badge;
 
阅读代码与编写的差别 
写代码其实比读代码难很多。比方说,现在让你把上面的代码擦掉,自己写一个开关的逻辑,就算你对上面的方案有印象,就算你借助了人工智能 ChatGPT,也没有那么容易——可能花很多时间在向 ChatGPT 描述问题上,而 ChatGPT 不一定对。
这个很像做数学题,上课听讲、都会,下来一做、不对。
再讨论细一点,怎么知道徽章(Badge)相关API呢?勤快一点就翻文档,偷懒一点就问 ChatGPT。但前提是你起码要知道有 Badge 这个概念,这或许也就是教程的作用,从“没有概念”到有一些,从有一些到有很多……
下一篇会开始编写代码,不是说直接贴出作者自己写的代码,而是让读者自己写。只有自己开始写了,才学得会。
关于犯错 
对新手,问题比较多大的是,很多地方不能错一个字符,比如“icons”写成了“icon”……
对于这点,个人有一些经验,后续有空细讲:
- 学习的时候主动犯错,故意弄坏代码,看看会发生什么。除了提前积累错误经验,还能让你明白备份的重要性;
 - 写一点代码,就看一下效果,这能免去很多定位错误的时间。有的人一下子写一坨代码,写爽了才跑一下,然后排查、定位错误要花几倍时间;
 - “被动”犯错之后立马自我排查,效果远不如: 
- 休息一会再来;
 - 让别人(或 AI)检查。