编写您的第一个浏览器扩展教程 - 第 2 部分

2025-06-10

编写您的第一个浏览器扩展教程 - 第 2 部分

本教程基于我在 2019 年纽约 Codeland 会议上举办的研讨会。

为了本教程的目的,我们将使用 Firefox,但大多数概念也适用于其他浏览器。

本教程的代码可以在这里找到

我们说到哪儿了?

在本教程的第 1 部分中,我们创建了一个有趣的小扩展,每十分钟提醒您退出 Twitter。

这挺有意思的(而且,如果你和我一样,觉得它挺实用的🤐),但说到浏览器扩展,你首先想到的很可能是那些对网页进行操作的扩展。要么添加内容,要么删除内容,要么改变外观。

在第 2 部分中,我们将重点讨论这种扩展。

操作你的 DOM?

对网页进行更改的 JavaScript 程序使用称为 DOM 操作的技术来实现。

DOM(域对象模型)是 HTML 页面的 JavaScript 表示。

JavaScript 内置了一些函数,用于添加、删除或修改 DOM,从而导致底层 HTML 页面也随之改变。这个过程称为 DOM 操作。

我们将在下一个扩展中使用 DOM 操作。

消除偏见

技术招聘过程中面临的主要问题之一是招聘中的隐性偏见。

招聘人员通常只花不到半分钟的时间浏览简历,却要在短时间内做出许多快速的决定。在这种情况下,我们的大脑自然会试图走捷径,默认选择那些它认为“安全”的选项。但问题是,这些捷径并不一定基于现实。

大量研究表明,如果有两份相同的简历,唯一的区别是其中一份简历上有白人男性的照片和姓名,而另一份简历上有传统上在科技领域代表性不足的人群的照片和姓名,那么白人男性简历会比 URM 获得更多的回应。

这并不一定是因为研究中的招聘经理试图表现出种族歧视/性别歧视,更可能是因为我们与生俱来的隐性偏见,而且很难纠正,特别是当你没有意识到这些偏见的时候。

(如果你还没有做过,我建议你做一下内隐联想测验(IAT)。我发现它的结果令人大开眼界。)

Martin Huack创建了一个有趣的扩展来解决这个问题,叫做Unbiasify。可以访问他们的网站了解它的功能。

我们将实施一小部分。我们将改变 LinkedIn 的显示方式,这样我们就不会看到任何候选人的照片。相反,我们会把个人资料照片换成一只小猫的照片!

(原始的 Unbiasify 扩展程序将个人资料图片替换为普通的灰色圆圈,但这很无聊。此外,互联网上永远不会有太多的小猫 ;)

让我们开始吧!

注意:如果您不想丢失我们在第一部分中编写的任何代码,您可以在此时创建一​​个新的分支。我们编写的所有代码都在这个 repo中。

  • 我们需要做的第一件事是转到我们的manifest.json并更改"matches"密钥以告诉我们的扩展程序在 LinkedIn 上运行:
    "content_scripts": [
        {
-            "matches": ["*://*.twitter.com/*"],
+            "matches": ["*://*.linkedin.com/*"],
             "js": ["first-extension.js"]
        }
    ]
Enter fullscreen mode Exit fullscreen mode
  • 如果我们在“about:debugging”中重新加载扩展程序并访问LinkedIn.com,我们应该会看到警报弹出。这只是为了确保一切正常。

  • 让我们摆脱中的所有代码first-extension.js

  • 在编写任何代码之前,我们需要弄清楚要编辑页面的哪些部分。由于我们想要替换个人资料图片,所以我们需要访问 LinkedIn,看看能否找到所有个人资料图片的共同点。

  • 让我们访问LinkedIn.com,在搜索栏中输入“软件工程师”,然后点击“人员”选项卡。这样我们就会得到一份优秀的软件工程师名单。我们要做的是更换个人资料图片。

  • 打开“检查”工具(ctrl+shift+i或右键单击页面并选择“检查元素”)。

  • 导航到其中一张个人资料图片,它看起来应该像这样:
    突出显示个人资料图片的 devtools 屏幕截图

  • 我们正在寻找一个所有个人资料图片都具有共同点的类名,但页面上的其他元素都没有。

  • 稍微玩了一下,似乎我们想要的类名是这个:EntityPhoto-circle-4

  • 事实上,假设LinkedIn 上的所有头像图片都采用相同的格式似乎是合理的EntityPhoto-[shape]-[size](为了节省您的精力,我已验证此假设的正确性),这意味着我们无需做任何额外的工作即可让我们的扩展程序在整个 LinkedIn 上正常工作!我们要做的就是找到一种方法来选择所有类名包含 的图片EntityPhoto

  • 让我们编写代码来实现这一点。将以下内容添加到first-extension.js

let images = document.querySelectorAll('img[class*="EntityPhoto"]')
Enter fullscreen mode Exit fullscreen mode
  • 我们使用 JavaScriptquerySelectorAll函数来获取所有类img名包含指定子字符串的元素"EntityPhoto"(CSS 选择器class*会选择类名中任何位置包含指定值的类)。这将返回一个img元素数组,我们将其赋值给变量images

  • 接下来我们需要做的是将src我们的个人资料图片的属性(当前指向实际的个人资料图片)换成通用的猫图片。

  • 您可以使用您自己的猫的图片,也可以使用来自clipartix的免费图片:
    聪明的小猫,可以成为一名出色的工程师

  • 无论您选择使用哪张图片,请将其保存到您的计算机中kitten.jpg并将其放在我们first-extension目录中名为的子目录中images

  • 接下来,我们需要将小猫图片添加到扩展程序中。将以下键/值对添加到manifest.json

    "content_scripts": [
        {
             "matches": ["*://*.linkedin.com/*"],
             "js": ["first-extension.js"]
        }
-   ]
+   ],
+   "web_accessible_resources": ["images/kitten.jpg"]

Enter fullscreen mode Exit fullscreen mode

(记得在数组后面添加逗号"content_scripts"

  • 现在我们可以遍历images之前创建的数组,并将所有的imgs 指向我们的小猫图片!我们将使用循环来实现for。将以下内容添加到first-extension.js
for (i = 0; i < images.length; i++) {
    images[i].src = browser.runtime.getURL("images/kitten.jpg")
}
Enter fullscreen mode Exit fullscreen mode
  • 我们所做的是遍历我们的images数组,对于其中的每一张图片,我们都调用它的img.src属性并将其分配给一个新的 URL;我们的小猫图片的 URL(该browser.runtime.getURL部分是获取我们的扩展的根 URL,每次加载扩展时它都会发生变化)。

  • 现在我们可以看看扩展程序是否正常工作了!前往“about:debugging”页面并重新加载扩展程序,然后返回 LinkedIn 并刷新页面。如果一切顺利,它应该如下所示:

LinkedIn 的截图,头像图片变成了一群小猫

故障排除:如果您无法使其工作,您可以尝试将您的代码与该分支中的代码进行比较。

  • 看起来应该可以正常工作,但如果你刷新页面并尝试向下滚动,你可能会注意到并非所有头像都变成了猫!页面后半部分的个人资料仍然包含头像!

  • 原因在于 LinkedIn(与许多其他网站一样)使用了所谓的“延迟加载”。简而言之,为了节省页面加载时间,LinkedIn 不会一次性加载整个页面,而是只加载页面的一部分,并在您向下滚动时加载其余部分。问题在于,我们扩展程序中的脚本只在页面加载时运行一次,因此脚本运行时页面上不存在的所有内容都不会受到影响。

  • 我们可以使用一个相对较新的 JavaScript 功能MutationObserver来解决这个问题,该功能可以“观察”页面(或其一部分)是否有任何变化或“突变”,当它注意到某些变化时,它会执行传递给它的函数(回调函数)。

注意:MutationObserverAPI 相对较新,可能无法在所有浏览器中使用

  • 我们要做的第一件事是将现有的逻辑包装在一个函数中,以便更容易地传递它:
+ function imageSubstituter(){
      let images = document.querySelectorAll('img[class*="EntityPhoto"]')

      for (i = 0; i < images.length; i++) {
          images[i].src = browser.runtime.getURL("images/kitten.jpg")
      }
+ }
Enter fullscreen mode Exit fullscreen mode
  • 接下来,让我们创建一个新MutationObserver对象并将我们的函数作为回调传递给它:
const observer = new MutationObserver(imageSubstituter)
Enter fullscreen mode Exit fullscreen mode
  • 我们创建的对象MutationObserver有一个observe接受两个参数的函数:一个要观察的 DOM 元素,以及作为 JavaScript 对象传递的一些配置选项。

  • 让我们首先编写我们的配置选项:

const config = { childList: true, subtree: true }
Enter fullscreen mode Exit fullscreen mode

这将告诉我们的观察者不仅要观察我们告诉它的元素,还要观察任何子元素。

  • 现在我们可以调用observersobserve函数了。我们将把需要观察的整个 HTML 页面主体以及我们编写的配置选项传递给它:
observer.observe(document.body, config)
Enter fullscreen mode Exit fullscreen mode
  • 现在,我们可以看看改进后的扩展程序是否正常工作了。前往“about:debugging”,重新加载扩展程序,然后返回 LinkedIn 并重新加载页面。向下滚动页面,您应该会看到所有头像和猫咪图片都在加载!

故障排除:如果扩展程序不起作用,请仔细检查是否一切正确(检查此处的代码以供参考)。

如果您确认所有操作正确,但仍然无法正常工作,则可能是您的浏览器不支持该MutationObserverAPI。如上所述,这是一个相对较新的功能,尚未得到广泛支持。

恭喜!

恭喜!我们现在已经创建了两个可用的浏览器扩展!

我希望我为您提供了足够的信息,以便您开始开发自己的浏览器扩展。

如果我确实激励您做出一些很棒的东西,请在这里或在Twitter上联系我并分享您的作品!

鏂囩珷鏉ユ簮锛�https://dev.to/yechielk/writing-your-first-browser-extension-tutorial-part-2-3g9p
PREV
每个 Web 开发人员都应该访问的 8 个网站
NEXT
For 循环是什么?GenAI LIVE!| 2025 年 6 月 4 日